用扩展运算符进行深拷贝的注意事项
数组和对象的拷贝方式有很多,此处只针对扩展运算符...对数组和对象的深拷贝方式进行说明。
还介绍一篇深拷贝的方法深拷贝的终极探索用扩展运算符深拷贝数组:
直接粘贴代码:
let arr = [1, 2, 3, 4, 5, 6];
let arr1 = [...arr];
arr1.push(7);
console.log(arr); //[1, 2, 3, 4, 5, 6]
console.log(arr1); //[1, 2, 3, 4, 5, 6, 7]
当数组是一维数组时,扩展运算符可以进行完全深拷贝,改变拷贝后数组的值并不会影响拷贝源的值。
但是,当数组为多维时:
let arr = [1, 2, 3, 4, 5, 6, [1, 2, 3]];
let arr1 = [...arr];
arr1.push(7);
arr1[arr1.length - 2][0] = 100;
console.log(arr); //[1, 2, 3, 4, 5, 6,[100, 2, 3]]
console.log(arr1); //[1, 2, 3, 4, 5, 6, [100, 2, 3],7]
由上可见,我们不难发现当改变拷贝后数组中第二层数组的值时,arr1arr1.length - 2 = 100;拷贝前数组第二层数组的值也跟着改变了。
对象同理:
当对象只有一层时:
let obj = {
name: "Wawa",
age: 13,
gender: "female"
};
let obj1 = {...obj
};
obj1.height = 165;
console.log(obj);//{name: "Wawa", age: 13, gender: "female"}
console.log(obj1);//{name: "Wawa", age: 13, gender: "female", height: 165}
可以用扩展运算符进行完全深拷贝。
但当对象有多层时:
let obj = {
name: "Wawa",
age: 13,
gender: "female",
hobby: {
a: 'Chinese',
b: 'Math',
c: 'English'
}
};
let obj1 = {...obj
};
obj1.hobby.a = "PE";
console.log(obj); //{name: "Wawa", age: 13, gender: "female",hobby:{a: "PE", b: "Math", c: "English"}}
console.log(obj1); //{name: "Wawa", age: 13, gender: "female", ,hobby:{a: "PE", b: "Math", c: "English"},height: 165}
扩展运算符并不能打散第二层对象的值,且无法对其进行深拷贝,拷贝前和拷贝后第二层对象的引用地址仍然是同一个,一方改变,另一方也改变。
结论:用扩展运算符对数组或者对象进行拷贝时,只能扩展和深拷贝第一层的值,对于第二层极其以后的值,扩展运算符将不能对其进行打散扩展,也不能对其进行深拷贝,即拷贝后和拷贝前第二层中的对象或者数组仍然引用的是同一个地址,其中一方改变,另一方也跟着改变。
另外有一个疑问,官方说用Object.assign()拷贝时是浅拷贝,可无论我怎么操作都是深拷贝的效果,望大家指出理解错误的地方,此处贴上测试的demo:
let obj3 = {
name: "Gucci",
age: 13,
gender: "female",
hobby: {
a: 'Chinese',
b: 'Math',
c: 'English'
}
};
let obj4 = Object.assign({}, obj3);
obj4.hobby.a = "Math";
obj3.age = 1000;
console.log(obj3);
console.log(obj4.age);
无论是一层还是二层,改变拷贝之后属性的值,拷贝前对象中的任何值并没有发生改变,且互不影响,这不是深拷贝吗???