我理解传播运算符制作对象的浅拷贝,即克隆对象引用与原始对象相同的引用。但实际行为似乎矛盾和混乱。
const oldObj = {a: {b: 10}};
const newObj = {...oldObj};
oldObj.a.b = 2;
newObj //{a: {b: 2}}
oldObj //{a: {b: 2}}
Run Code Online (Sandbox Code Playgroud)
上述行为是有道理的,newObj 也通过更新 oldObj 来更新,因为它们引用相同的位置。
const oldWeirdObj = {a:5,b:3};
const newWeirdObj = {...oldWeirdObj};
oldWeirdObj.a=2;
oldWeirdObj //{a:2,b:3}
newWeirdObj //{a:5,b:3}
Run Code Online (Sandbox Code Playgroud)
我不明白,为什么 newWeirdObj 没有像 oldWeirdObj 那样更新?如果我没有错,他们仍然指的是同一个位置,但为什么更新到 oldWeirdObj 而不更新 newWeirdObj ?
Saj*_*med 16
所以,对于这个问题,你要明白什么是shallowcopy和deepcopy。
浅拷贝是对象的按位拷贝,它通过复制原始对象的内存地址来创建新对象。也就是说,它创建一个新对象,其内存地址与原始对象相同。
深拷贝,使用动态分配的内存复制所有字段。也就是说,复制对象的每个值都获得了一个新的内存地址,而不是原始对象。
现在,点差运算符是做什么的?如果数据没有嵌套,它会深度复制数据。对于嵌套数据,深度拷贝嵌套数据的最顶层数据和浅拷贝。
在你的例子中,
const oldObj = {a: {b: 10}};
const newObj = {...oldObj};
Run Code Online (Sandbox Code Playgroud)
它深拷贝顶层数据,即它给属性a,一个新的内存地址,但它浅拷贝嵌套对象,即{b: 10}它现在仍然引用原始oldObj的内存位置。
如果你不相信我检查这个例子,
const oldObj = {a: {b: 10}};
const newObj = {...oldObj};
Run Code Online (Sandbox Code Playgroud)
const oldObj = {a: {b: 10}, c: 2};
const newObj = {...oldObj};
oldObj.a.b = 2; // It also changes the newObj `b` value as `newObj` and `oldObj`'s `b` property allocates the same memory address.
oldObj.c = 5; // It changes the oldObj `c` but untouched at the newObj
console.log('oldObj:', oldObj);
console.log('newObj:', newObj);Run Code Online (Sandbox Code Playgroud)
你看到的c财产newObj是原封不动的。
我认为有几种方法。一种常见且流行的方法是使用JSON.stringify()和JSON.parse()。
.as-console-wrapper {min-height: 100%!important; top: 0;}Run Code Online (Sandbox Code Playgroud)
const oldObj = {a: {b: 10}, c: 2};
const newObj = JSON.parse(JSON.stringify(oldObj));
oldObj.a.b = 3;
oldObj.c = 4;
console.log('oldObj', oldObj);
console.log('newObj', newObj);Run Code Online (Sandbox Code Playgroud)
现在,newObj具有全新的内存地址,任何更改oldObj都不会影响newObj.
另一种方法是将oldObj属性一个一个地分配到newObj的新分配的属性中。
.as-console-wrapper {min-height: 100%!important; top: 0;}Run Code Online (Sandbox Code Playgroud)
const oldObj = {a: {b: 10}, c: 2};
const newObj = {a: {b: oldObj.a.b}, c: oldObj.c};
oldObj.a.b = 3;
oldObj.c = 4;
console.log('oldObj:', oldObj);
console.log('newObj:', newObj);Run Code Online (Sandbox Code Playgroud)
有一些库可用于深拷贝。你也可以使用它们。
复制数组时,扩展语法有效地深入一层。因此,它可能不适合复制多维数组,如以下示例所示。(Object.assign()也是如此)
let x = [1,2,3];
let y = [...x];
y.shift(); // 1
console.log(x); // 1, 2, 3
console.log(y); // 2, 3
let a = [[1], [2], [3]];
let b = [...a];
b.shift().shift(); // 1
// Oh no! Now array 'a' is affected as well:
a
// [[], [2], [3]]Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3390 次 |
| 最近记录: |