【进阶】深拷贝浅拷贝的区别,以及如何手写实现深浅拷贝

一、基本类型和引用类型

基本类型:string,number,boolean,null,undefiend,symbol

引用类型:Function,Array,Object

1、基本数据类型的特点:直接存储在栈(stack)中的数据

2、引用数据类型的特点:存储的是该对象在栈中引用,真实的数据存放在堆内存里

二、浅拷贝和深拷贝

1、浅拷贝、深拷贝的概念
  • 浅拷贝就是创建一个新对象,这个对象对原始对象进行了精确拷贝。
    若属性是基本类型,拷贝的就是属性的值;
    若属性是引用类型,拷贝的就是内存地址,
    若其中一个对象改变了这个地址,就会影响到另一个对象。
  • 深拷贝就是将一个对象完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,修改新对象不会影响到原对象。
2、赋值、浅拷贝、深拷贝区别

浅拷贝、深拷贝主要都是针对object或者array数据类型的,所以比较的前提是针对引用类型。

  • 当我们把一个对象赋值给一个新的变量时,赋的其实是该对象的在栈中的地址,而不是堆中的数据。
  • 深拷贝:重新在堆中创建内存,拷贝前后对象的基本数据类型互不影响,但拷贝前后对象的引用类型因共享同一块内存,会相互影响。
  • 从堆内存中开辟一个新的区域存放新对象,对对象中的子对象进行递归拷贝,拷贝前后的两个对象互不影响。

三、浅拷贝实现方式

1. Object.assign()

Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。但是 Object.assign() 进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。

var obj = { a: {a: "kobe", b: 39} };
var initalObj = Object.assign({}, obj);
initalObj.a.a = "wade";
console.log(obj.a.a); // wade
// 注意:当object只有一层的时候,是深拷贝
let obj = {
  username: 'kobe'
};
let obj2 = Object.assign({},obj);
obj2.username = 'wade';
console.log(obj);//{username: "kobe"}
  1. Array.prototype.concat() 修改新对象会改到原对象
  2. Array.prototype.slice()

四、深拷贝实现方式

  1. JSON.parse(JSON.stringify())
  2. 手写递归方法
  3. 函数库lodash

五、手写函数实现深拷贝和浅拷贝

// 手写实现深拷贝和浅拷贝之浅拷贝:
let shallowObj01 = {
  name: "小王",
  age: "18",
  hobbit: ["唱歌", "跳舞", "吃火锅"],
};
let shallowObj02 = shallowClone(shallowObj01);
shallowObj02["name"] = "大王";
shallowObj02["age"] = "28";
shallowObj02["hobbit"].push("打游戏");

function shallowClone(obj) {
  let target = {};
  for (let i in obj) {
    // eslint-disable-next-line no-prototype-builtins
    if (obj.hasOwnProperty(i)) {
      target[i] = obj[i];
    }
  }
  return target;
}
console.log("shallowObj01", shallowObj01);
console.log("shallowObj02", shallowObj02);

// 手写实现深拷贝和浅拷贝之深拷贝:
let deepObj01 = {
  name: "cat",
  age: "2",
  hobbit: ["sing", "dance"],
};
let deepObj02 = deepClone(deepObj01);
deepObj02["name"] = "布丁";
deepObj02["age"] = "5";
deepObj02.hobbit.push("eat ice cream");

function deepClone(obj) {
  if (obj === null) return obj;
  if (obj instanceof Date) return new Date(obj);
  if (obj instanceof RegExp) return new RegExp(obj);
  if (typeof obj !== "object") return obj;

  let cloneObj = new obj.constructor();
  for (let i in obj) {
    if (obj.hasOwnProperty(i)) {
      cloneObj[i] = deepClone(obj[i]);
    }
  }
  return cloneObj;
}
console.log("deepObj01", deepObj01);
console.log("deepObj02", deepObj02);

你可能感兴趣的:(【进阶】深拷贝浅拷贝的区别,以及如何手写实现深浅拷贝)