什么是浅拷贝和深拷贝

173 阅读2分钟

1. 什么是浅拷贝

定义:复制一层对象的属性,并不包括对象里面的为引用类型的数据,当改变拷贝的对象里面的引用类型时,源对象也会改变。

  • 也就是说浅拷贝只能复制基本数据类型,对于引用数据类型的数据只能复制该类型数据的一个地址,与原对象共同使用该数据,一旦有一方改变,就会改变源对象
  • JS基本数据类型包括:String、Boolean、Number、Undefined、Null
  • 引用数据类型包括:Object(Array、Date、Function、RegExp)
  • 基本数据类型与引用数据类型的区别
    • 数据存放的位置不同:基本数据存放在栈内存中,引用数据类型放在堆内存
    • 数据拷贝方式不同:基本数据的拷贝是从栈内存中直接复制一份,而引用类型数据则需要从栈内存中找到要复制的对象的地址,引过来使用,例如:newObject()复制oldObject() ,虽然newObject()的内容与oldObject()的内容相同,但是改变newObject()中的属性的值,相应的oldObject()中的属性也会改变
  • 例如:
//浅拷贝,双向改变,指向同一片内存空间
var arr1 = [1, 2, 3];
var arr2 = arr1;
arr1[0] = 'change';
console.log(arr1);   //change,2,3
console.log(arr2);   //change,2,3

2.什么是深拷贝

定义:重新开辟一个内存空间,需要递归拷贝对象里的引用,直到子属性都为基本类型。两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性。

  • 浅拷贝只是复制了对象的地址,新旧对象使用统一内存,而深拷贝是完全为新对象开辟了一块新的内存,然后将新对象放进去,之后两者互不影响彼此
  • 如何实现深拷贝
    • 数组深拷贝:
      • concat:
          var a=[1,2,3]
          var c=[];
          var b=c.concat(a);
          b.push(4);
          console.log(b);//1,2,3,4
          console.log(a)//1,2,3
      
      • slice:
          var a=[1,2,3]
          var b=a.slice(0);
          b.push(4);
          console.log(b);//1,2,3,4
          console.log(a)//1,2,3
      
      • for循环
    • 对象深拷贝
      • stringify和parse 方法
      var a=[1,2,3]
      var c=JSON.stringify(a);
      var b=JSON.parse(c);
      b.push(4);
      console.log(b);//1,2,3,4
      console.log(a)//1,2,3
      
      -for循环(此处就不举例说明了)