JS:如何使用Object.assign将属性复制到对象数组中?

时间:2018-01-11 20:51:35

标签: javascript javascript-objects

我试图将一个对象的键值对复制到一个数组中的每个不同对象中。



const propsToDuplicate = {
  foo: 'foo',
  bar: 'bar'
};

const items = [{
    num: 1
  },
  {
    num: 2
  }
];

const result = items.map(item => {
  console.log('item: ', item);
  const moar = Object.assign(propsToDuplicate, item);
  console.log('item with more stuff: ', moar);
  return moar;
});

console.log(result);




问题:

  1. 为什么我最终得到num = 2的对象的两个实例?
  2. 如何执行此操作以使最终结果如下?
  3. 期望的结果:

    [ { foo: 'foo', bar: 'bar', num: 1 },
      { foo: 'foo', bar: 'bar', num: 2 } ]
    

    这是沙箱:

    https://repl.it/@montrealist/array-map-and-object-assign-weirdness

2 个答案:

答案 0 :(得分:2)

Object.assign(a, b, c)会将abc中的所有内容分配到作为assign()的第一个参数的对象中。

在您的情况下,您使用propsToDuplicate作为第一个参数,这意味着每次调用assign()时,propsToDuplicate都会发生变异。

const moar = Object.assign(propsToDuplicate, item);更改为const moar = Object.assign({}, propsToDuplicate, item);,您应该好好去。

答案 1 :(得分:1)

  

为什么我最终得到了具有num = 2

的对象的两个实例

因为您的代码中有moar === propsToDuplicate。您已将所有这些属性/值分配给同一个对象。并且该数组的所有索引都引用相同的对象。

  

如何执行此操作以使最终结果如下?

将属性分配给空对象:

const morar = Object.assign({}, propsToDuplicate, item);
  

解决方法是返回JSON.parse(JSON.stringify(moar));

这不起作用,因为您仍然将所有属性分配到同一个对象中,但是您返回每次迭代的快照。如果您只将另一个属性添加到items中的第一个对象,您也会看到它出现在其他(稍后)项目中。

Plus JSON.parse(JSON.stringify(...))是克隆对象的一种丑陋方法。

  

或者我可以简单地翻转参数 - 这会有效吗? Object.assign(item, propsToDuplicate);

是/否/有点/更好不......我必须解释。

在这种情况下,您将使用item中的属性覆盖propsToDuplicate中的属性,并且您将改变items数组中的对象。在您当前的代码中,这没有任何区别,但如果某些item具有foobar属性,或者propsToDuplicate包含num,则'd在结果中覆盖该属性。

解释说:Object.assign()通常用于组合一些具有默认值的配置对象。

let options = Object.assign({}, defaults, config);

这将采用一个空的Object,然后首先将所有默认值写入其中,然后使用配置中传递的值覆盖默认值的soem。

,而

let options = Object.assign(config, defaults);

将使用默认值覆盖所有自定义配置。

然后就是突变的问题。变异的问题在于,根据您从哪里获取对象以及在何处引用它,您更改对象可能会在应用程序的另一端引入错误,在一些完全不相关的代码中。然后调试并发现错误。