为什么要传播语法静音数组中的对象

时间:2018-02-01 20:36:17

标签: javascript ecmascript-6

如你所知,有多种方法可以复制数组而无需复制引用,我注意到了

如果你有以下数组:

const x = [{age:25},{age:15}];

并且您需要使用扩展语法复制该数组,如此

const z = [...x];

更新z数组后,它将更新器官数组

z[0].age = 50

但是如果你使用像这样的Json解析器复制数组

const z = JSON.parse(JSON.stringify(x));

你不会面对这个问题,也不知道为什么会发生这种情况。

提前致谢。

3 个答案:

答案 0 :(得分:2)

{age:25}是一个对象。在第一种情况下复制数组的内容时,克隆该数组,但该数组包含对象的引用;然后,克隆的数组包含相同的引用。因此,当您更改第一个对象时,您还更改了第二个对象 - 因为它们是同一个对象,而不仅仅是一个相似的对象。

作为类比:杰克和梅格属于DnD俱乐部。然后形成一个动漫俱乐部,来自DnD俱乐部的每个人也加入了动漫俱乐部。如果动漫俱乐部的每个人都获得动漫俱乐部会员卡,那么DnD俱乐部(杰克和梅格)的人是否有动漫会员卡?为什么呢?

当您浏览JSON时,您会创建看起来像原始对象的新对象,但它们不是同一个对象。杰克和梅格加入了DnD俱乐部。动漫俱乐部开放,他们各自的同卵双胞胎Joe和Peg加入了动漫俱乐部。如果乔和佩格获得动漫俱乐部会员卡,杰克和梅格将不会有一张。

答案 1 :(得分:1)

您正在改变数组中的对象,该对象仍具有相同的引用 数组传播只会执行浅复制,它仍然会对其中的对象使用相同的引用。

您可以在数组上使用Array.prototype.map并使用object spread syntax which is a proposal in stage 3返回对象的新副本(浅拷贝):

const z = x.map(o => ({...o}));

运行示例:

const x = [{age:25},{age:15}];
const z = x.map(o => ({...o}));
z[0].age = 50

console.log(x);

答案 2 :(得分:0)

这不是一个奇怪的问题,这只是对象的工作方式。

JSON.stringify(x)以字符串格式创建对象的副本,完全断开对原始对象的引用( x ),然后字符串是使用JSON.parse

重新水合成对象

通过使用[...x],您只需在另一个数据结构中存储对象及其属性的引用。这就是为什么虽然它们似乎在改变不同的东西,因为它们是不同的变量,但它们只不过是对内存中相同位置的引用。对该位置的数据进行任何更改,而不是变量。它们共享相同的数据池。