我了解传播运算符会制作对象的浅表副本,即克隆对象引用与原始对象相同的引用。但实际行为似乎自相矛盾和令人困惑。
const oldObj = {a: {b: 10}};
const newObj = {...oldObj};
oldObj.a.b = 2;
newObj //{a: {b: 2}}
oldObj //{a: {b: 2}}
以上行为是有道理的,newObj 也通过更新 oldObj 来更新,因为它们引用相同的位置。
const oldWeirdObj = {a:5,b:3};
const newWeirdObj = {...oldWeirdObj};
oldWeirdObj.a=2;
oldWeirdObj //{a:2,b:3}
newWeirdObj //{a:5,b:3}
我不明白,为什么 newWeirdObj 没有像 oldWeirdObj 那样更新?如果我没记错的话,他们仍然指的是同一个位置,但是为什么更新到 oldWeirdObj 而不是更新 newWeirdObj 呢?
原文由 richa Singh 发布,翻译遵循 CC BY-SA 4.0 许可协议
所以,对于这个问题,你要明白什么是
shallow
拷贝和deep
拷贝。浅拷贝 是一个对象的逐位拷贝,它通过复制原始对象的内存地址来创建一个新对象。也就是说,它创建了一个内存地址与原始对象相同的新对象。
深拷贝,用动态分配的内存复制所有字段。也就是说,复制对象的每个值都会获得一个新的内存地址,而不是原始对象。
现在,差价操作员做什么?如果数据没有嵌套,它会深度复制数据。对于嵌套数据,它会深拷贝最顶层数据和浅拷贝嵌套数据。
在你的例子中,
它深复制顶级数据,即它给属性
a
一个新的内存地址,但它浅复制嵌套对象即{b: 10}
现在仍然指的是原来的oldObj
的内存位置。如果你不相信我检查这个例子,
您会看到 --- 的
newObj
c
属性未受影响。如何深度复制一个对象。
我认为有几种方法。一种常见且流行的方法是使用
JSON.stringify()
和JSON.parse()
。现在,
newObj
有了全新的内存地址,对oldObj
的任何更改都不会影响newObj
。另一种方法是将
oldObj
属性一个一个地分配到newObj
的新分配属性中。有一些库可用于深层复制。你也可以使用它们。