什么是浅拷贝?可以这么理解:创建一个新的对象,把原有的对象属性值,完整地拷贝过来。其中包括了原始类型的值,还有引用类型的内存地址。
让我们用 Object.assign 来改写一下上面的例子:
2 const obj2 = Object.assign({}, obj);
3 obj2.a = 3;
4 console.log(obj.a); // 1
Ok,改变了 obj2 的 a 属性,但 obj 的 a 并没有发生变化,这正是我们想要的。
可是,这样的拷贝还有瑕疵,再改一下例子:
1 const arr = [{a:1,b:2}, {a:3,b:4}];
2 const newArr = [].concat(arr);
4 newArr.length = 1; // 为了方便区分,只保留新数组的第一个元素
5 console.log(newArr); // [{a:1,b:2}]
6 console.log(arr); // [{a:1,b:2},{a:3,b:4}]
8 newArr[0].a = 123; // 修改 newArr 中第一个元素的a
9 console.log(arr[0]); // {a: 123, b: 2},竟然把 arr 的第一个元素的 a 也改了
oh,no!这不是我们想要的...
经过一番查找,才发现:原来,对象的 Object.assign(),数组的 Array.prototype.slice() 和 Array.prototype.concat(),还有 ES6 的 扩展运算符,都有类似的问题,它们都属于 浅拷贝。这一点,在实际工作中处理数据的组装时,要格外注意。
所以,浅拷贝应该这样定义:只拷贝第一层的原始类型值,和第一层的引用类型地址。
网友评论