JS 浅拷贝与深拷贝

187 阅读1分钟

总结

  1. 浅拷贝只复制对象第一层的属性,新旧对象的子对象共享一块内存。Object.assign()、Array 的 concat、slice 方法
  2. 深拷贝实现新旧对象数据相同,但是存在各自独立的内存中。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;
}