• 浅拷贝:拷贝对象的引用地址,而不是拷贝对象本身,新老对象共用一块内存
  • 深拷贝:拷贝一个一摸一样的对象,新老对象不共享内存,修改新对象不会影响到老对象
  • 对比示意图image.png

    浅拷贝实现方式

  1. 赋值实现
  2. Object.assign()

    1. var obj = { a: {a: "hello", b: 21} };
    2. var initalObj = Object.assign({}, obj);
    3. initalObj.a.a = "changed";
    4. console.log(obj.a.a); // "changed"
  3. 函数库lodash的clone方法

  4. 展开运算符 {…obj}

    1. let obj1 = { name: 'Kobe', address:{x:100,y:100}}
    2. let obj2= {... obj1}
  5. Array.prototype.concat()

    1. let arr = [1, 3, {
    2. username: 'kobe'
    3. }];
    4. let arr2 = arr.concat();
    5. arr2[2].username = 'wade';
    6. console.log(arr); //[ 1, 3, { username: 'wade' } ]
  6. Array.prototype.slice()

    1. let arr = [1, 3, {
    2. username: ' kobe'
    3. }];
    4. let arr3 = arr.slice();
    5. arr3[2].username = 'wade'
    6. console.log(arr); // [ 1, 3, { username: 'wade' } ]

    深拷贝方式

  7. lodash的cloneDeep方法

  8. 递归拷贝
  9. JSON.stringify()把对象转成字符串,再用JSON.parse把字符串转成新的对象
  10. Object.assign()当对象只有一层的话可以用此方法实现拷贝

    递归实现深拷贝有什么隐患

  11. 对象层次很深的时候,会出现爆栈的情况

解决办法:

  1. 循环引用的情况,即对象的属性间接或直接的引用了自身,导致递归进入死循环,栈溢出。

解决循环引用问题,我们可以额外开辟一个存储空间,来存储当前对象和拷贝对象的对应关系,当需要拷贝当前对象时,先去存储空间中找,有没有拷贝过这个对象,如果有的话直接返回,如果没有的话继续拷贝。
这个存储空间,需要可以存储key-value形式的数据,且key可以是一个引用类型,我们可以选择Map这种数据结构
参考