我试图将一个对象的键值对复制到一个数组中的每个不同对象中。
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);

问题:
num
= 2的对象的两个实例? 期望的结果:
[ { foo: 'foo', bar: 'bar', num: 1 },
{ foo: 'foo', bar: 'bar', num: 2 } ]
这是沙箱:
https://repl.it/@montrealist/array-map-and-object-assign-weirdness
答案 0 :(得分:2)
Object.assign(a, b, c)
会将a
,b
和c
中的所有内容分配到作为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
具有foo
或bar
属性,或者propsToDuplicate
包含num
,则'd在结果中覆盖该属性。
解释说:Object.assign()
通常用于组合一些具有默认值的配置对象。
let options = Object.assign({}, defaults, config);
这将采用一个空的Object,然后首先将所有默认值写入其中,然后使用配置中传递的值覆盖默认值的soem。
,而
let options = Object.assign(config, defaults);
将使用默认值覆盖所有自定义配置。
然后就是突变的问题。变异的问题在于,根据您从哪里获取对象以及在何处引用它,您更改对象可能会在应用程序的另一端引入错误,在一些完全不相关的代码中。然后调试并发现错误。