总结
- 浅拷贝只复制对象第一层的属性,新旧对象的子对象共享一块内存。
Object.assign()、Array 的 concat、slice 方法
。 - 深拷贝实现新旧对象数据相同,但是存在各自独立的内存中。
lodash 的_cloneDeep、JSON.parse(JSON.stringify())、以及手写递归方法等
。
浅拷贝
浅拷贝只复制对象第一层的属性,而不复制对象本身,新旧对象的子对象还是共享同一块内存。
实现方法
- Object.assign():对象只有一层时,是深拷贝
- 展开语法 b = {…a} 与 Object.assign() 一致
- Array.prototype.concat()
- Array.prototype.slice()
let arr = [1,[2,2]];
let cArr = [].concat(arr);
cArr[0] = 2;
cArr[1][0] = 1;
console.log(arr.toString()); //2,1,2
console.log(cArr.toString()); //1,1,2
深拷贝
深拷贝是在拷贝数据的时候,将数据的所有引用结构都拷贝一份。简单的说就是,内存中存在两个数据结构完全相同又相互独立的数据,将引用类型进行复制,而不是复制其引用关系。
实现方法
- 热门的函数库 lodash,提供 _.cloneDeep 用来做深拷贝
- jquery 提供一个 $.extend 可以用来做深拷贝
- JSON.parse(JSON.stringify()),
问题:会忽略 undefined symbol,不能序列化函数,不能解决循环引用,不能正确处理 new Date() 不能处理正则。
手写递归
递归实现深拷贝的原理:要拷贝一个数据,我们肯定要去遍历它的属性,如果这个对象的属性仍是对象,继续使用这个方法,如此往复。
function deepCopy(p, c) {
var c = c || {};
for(var i in p){
if(typeof p[i] === 'object'){
c[i] = (p[i].constructor === Array)?[]:{};
deepCopy(p[i],c[i]);
}else{
c[i] = p[i];
}
}
return c;
}