简体   繁体   English

使用map()时克隆对象属性的最佳方法是什么?

[英]What is the best approach to clone objects properties when using map()?

I want to add a new property (contactDetails.countryName) and assign a value to a nested object stored in an array called users using the function map(). 我想添加一个新属性(contactDetails.countryName),并使用函数map()为存储在名为users的数组中的嵌套对象赋值。

I've recently learned that I should use the spread operator (...) and then create / assign the new property in order to avoid mutating my original array of objects so I've developed 2 different implementations for this but I'm not really confident I'm following the best practices to accomplish I want to regarding the semantic and performance. 我最近了解到我应该使用扩展运算符(...),然后创建/赋值新属性,以避免改变我原来的对象数组,所以我为此开发了2个不同的实现,但我不是我非常自信我正在遵循最佳实践来实现我想要的语义和性能。

What would be the best approach to accomplish what I want to do in your opinion? 在您看来,完成我想要做的最佳方法是什么?

const countries = [
  { id: 3, countryName : "UK" },
  { id: 4, countryName : "Spain" },
  { id: 6, countryName : "Germany"}
];


const users = [
  { id : 1,
    name: "Douglas Camp",
    dateOfBirth: "23-06-1984",
    contactDetails:
      {
        country: 3,
        phone: "7373724997"
      }
  },
  {
    id : 2,
    name: "Martin Stein",
    dateOfBirth: "19-08-1992",
    contactDetails:
      {
        country: 6,
        phone: "3334343434"
      }
  },
];


const usersData = users.map(user=> {

// Version 1 : using spreading operator twice 

const newUser = {
    ...user,
    contactDetails: {
      ...user.contactDetails,
      countryName: countries.find(c=> c.id == user.contactDetails.country).countryName
    }
  };  
  return newUser;
});

// Version 2: copying the original object property and using spread operator only for cloning the nested object properties

const newUser = {
    id: user.id,
    name: user.name,
    dateOfBirth: user.dateOfBirth,
    contactDetails: {
      ...user.contactDetails,
      countryName: countries.find(c=> c.id == user.contactDetails.country).countryName
    }
  };

console.log(users);
console.log(usersData);

Here is an approach you can consider: 您可以考虑以下方法:

  • First of all I would Array.reduce the countries to a Map so you can get them via key / value or in this case by countries.get(key) and avoid filtering that array every time. 首先,我将Array.reduce国家/地区转换为Map,以便您可以通过key / value或在这种情况下通过countries.get(key)获取它们,并避免每次都过滤该数组。

  • You can map through the users and for each one create a new object. 您可以通过用户进行映射,并为每个用户创建一个新对象。 In this case I call them accounts . 在这种情况下,我称他们为accounts

  • You can also consider using Object.assign 您还可以考虑使用Object.assign

  • Note that both ... operator and Object.assign are shallow clone approaches . 请注意这两个...运营商和Object.assign浅克隆方法 They do not recursively clone the nested objects/children. 它们不会递归克隆嵌套对象/子对象。 For that you can use JSON.stringify and JSON.parse etc. 为此你可以使用JSON.stringifyJSON.parse等。

 let countries = [ { id: 3, countryName : "UK" }, { id: 4, countryName : "Spain" }, { id: 6, countryName : "Germany"} ].reduce((r,{id, countryName}) => (r.set(id, countryName), r), new Map()) // reduce with Map let users = [ { id : 1, name: "Douglas Camp", dateOfBirth: "23-06-1984", contactDetails: { country: 3, phone: "7373724997" } }, { id : 2, name: "Martin Stein", dateOfBirth: "19-08-1992", contactDetails: { country: 6, phone: "3334343434" } }, ]; let accounts = users.map(user => Object.assign({}, user, { // <-- map through contactDetails: { ...user.contactDetails, countryName: countries.get(user.contactDetails.country) // <-- get by key } })) users[0].id = 2 // <-- modify users users[0].contactDetails.phone = "00000" console.log(users, accounts) // <-- no changes to accounts 

Notice when we update the users[0].id and users[0].contactDetails.phone the accounts values did not update. 请注意,当我们更新users[0].idusers[0].contactDetails.phone ,帐户值未更新。

I normally use version 1, the spread operator twice. 我通常使用版本1,扩展运算符两次。 I also would consider checking out immer which allows you to do mutable updates on a cloned draft and handles merging it back for you. 我还会考虑检查immer ,它允许你对克隆的草稿进行可变更新并处理合并它。

const newUser = immer(user, draft => {
  draft.contactDetails.countryName = countries.find(
    c => c.id == user.contactDetails.country).countryName
  )
})

Just edit the specific property you want and immer handles copying the rest of it. 只需编辑您想要的特定属性,immer处理复制其余属性。

Cloning and merging MapsSection Just like Arrays, Maps can be cloned: 克隆和合并MapsSection就像数组一样,可以克隆地图:

var original = new Map([
  [1, 'one']
]);

var clone = new Map(original);

console.log(clone.get(1)); // one
console.log(original === clone); // false. Useful for shallow comparison

I personally like to use Version 1, as it makes your code much less redundant and easier to read. 我个人喜欢使用版本1,因为它使您的代码更少冗余且更易于阅读。 It also passes all the properties of 'user' down to newUser. 它还将'user'的所有属性传递给newUser。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 将对象作为键(不是字符串而是唯一对象)的关联映射的javascript方法是什么? - What is the javascript approach to an associative map with objects as keys (not strings but unique objects)? 在Knockout中使用集合,迭代的最佳方法是什么? - Using collections in Knockout, what is the best approach for iteration? map 路由与用户权限反应的最佳方法是什么? - What's the best approach to map routes in react with user privilege? 当用户使用 Leaflet JS 在导航模式下与 map 交互时,复制 Google 地图“重新居中”的最佳方法 - Best approach to replicate Google Map's "re-center" when user interacts with the map in navigation mode using Leaflet JS 创建自定义角度材质主题时,最佳方法是什么? - What is the best approach when creating a custom angular material theme? 从两个单独的JavaScript对象合并属性的最佳方法是什么? - What is the best way to merge properties from two separate JavaScript objects? 比较两个对象中选定属性的最佳方法是什么 - what's the best way to compare selected properties in two objects 在ASP.NET项目中使用缓存的最佳方法是什么? - What is the best approach of using cache in ASP.NET project? 使用点击刷新表格正文的最佳方法是什么 - What is the best approach to refresh table body using on click 使用webpack加载jQuery模块的最佳方法是什么 - What is the best approach to load jQuery modules using webpack
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM