JS深拷贝和浅拷贝

深拷贝和浅拷贝是只针对Object和Array这样的引用数据类型的。
1.JS数据类型
基本数据类型:Boolean、String、Number、null、undefined
引用数据类型:Object、Array、Function、RegExp、Date等
2.数据类型的复制
基本数据类型的复制,是按值传递的
引用数据类型的复制,是按引用(地址指针)传值
深拷贝和浅拷贝都只针对引用数据类型,浅拷贝会对对象逐个成员依次拷贝,但只复制内存地址,而不复制对象本身,新旧对象成员还是共享同一内存;深拷贝会另外创建一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
区别:浅拷贝只复制对象的第一层属性,而深拷贝会对对象的属性进行递归复制。

浅拷贝

对象赋值:当把一个对象赋值给一个新的变量时,赋的对象是该对象在栈中的地址,而不是堆中的数据。

var fruits = ["Banana", "Orange", "Apple", "Mango"];
      var obj=fruits;
      obj[1]="water";
      console.log("fruits",fruits);
      console.log("obj",obj)
图片.png

浅拷贝是按位拷贝(位拷贝拷贝的是地址,而值拷贝则拷贝的是内容)对象,它会创建一个新对象,对原有对象的成员进行依次拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是引用类型,拷贝的就是内存地址。因此如果新对象中的某个对象成员改变了地址,就会影响到原有的对象。

//手写浅拷贝
      function shallowCopy(fruits) {
        let obj = Array.isArray(fruits) ? [] : {};
        for (let i in fruits) {
          obj[i] = fruits[i];
        }
        return obj;
      }
      var fruits = ["Banana", "Orange", "Apple", ["Mango", "blue"]];
      var obj = shallowCopy(fruits);
      obj[2] = "water";
      obj[3][0] = "water";
      console.log("fruits", fruits);
      console.log("obj", obj);
图片.png
  1. 浅拷贝的实现
  • Object.assign()
    Object.assign()方法可以把源对象自身的任意多个的可枚举属性拷贝给目标对象,然后返回目标对象,但是Object.assign()进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。
      var fruits = ["Banana", "Orange", "Apple", ["Mango", "blue"]];
      var obj = Object.assign([], fruits);
      obj[2] = "water";
      obj[3][0] = "water";
      console.log("fruits", fruits);
      console.log("obj", obj);
图片.png
  • Array.prototype.concat()和Array.prototype.slice()
    Array的slice和contact方法都不会修改原数组,而是会返回一个对原数组进行浅拷贝的新数组。这两种方法同Object.assign()一样,都是对第一层属性依次拷贝,如果第一层的属性是基本数据类型,就拷贝值;如果是引用数据类型,就拷贝内存地址。
      var obj=fruits.slice();

深拷贝

对对象的属性中所有引用类型的值,遍历到是基本类型的值为止。

  • JSON.parse(JSON.stringify())
    原理:用JSON.stringify()将对象转成字符串,再用JSON.parse()把字符串解析成对象。
      var obj=JSON.parse(JSON.stringify(fruits));
图片.png
  • 函数库
    也可以使用一些函数库,比如函数库lodash,也有提供_.cloneDeep用来做深拷贝;
var _ = require('lodash');
var obj1 = {
  a: 1,
  b: { f: { g: 1 } },
  c: [1, 2, 3]
};
var obj2 = _.cloneDeep(obj1);
console.log(obj1.b.f === obj2.b.f);
// false

总结:
浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。
深拷贝就是在拷贝数据的时候,将数据的所有引用结构都拷贝一份。


图片.png

你可能感兴趣的:(JS深拷贝和浅拷贝)