Skip to content
On this page

深拷贝的实现 ​

什么是深拷贝? ​

深拷贝与浅拷贝最大的不同就在于,当遇到属性值为引用类型的时候,它会新建一个引用类型并将对应的值复制给它,因此新对象获得的一个是新的引用类型而不是原有类型的引用。

深拷贝对于一些对象可以使用 JSON 的两个函数来实现,但是由于 JSON 的对象格式比 js 的对象格式更加严格,所以如果属性值里边出现函数或者 Symbol 类型的值时,会转换失败。

代码实现 ​

JSON.stringify() ​

  • JSON.parse(JSON.stringify(obj)) 是目前比较常用的深拷贝方法之一,它的原理就是利用 JSON.stringify() 将js对象序列化(JSON字符串),再使用 JSON.parse() 来反序列化(还原)js对象。
  • 这个方法可以简单粗暴地实现深拷贝,但是还存在问题,要拷贝的对象中如果有函数,undefined 或 symbol,当使用过 JSON.stringify() 进行处理之后,都会消失。
js
let obj1 = {  a: 0,
              b: {
                 c: 0
                 }
            };
let obj2 = JSON.parse(JSON.stringify(obj1));
obj1.a = 1;
obj1.b.c = 1;
console.log(obj1); // {a: 1, b: {c: 1}}
console.log(obj2); // {a: 0, b: {c: 0}}

手写实现 ​

思路:

  1. 遍历源对象的所有属性。
  2. 对于每个属性,如果是基本类型,则直接赋值给目标对象。
  3. 如果是引用类型(如对象或数组),则递归调用深拷贝函数,创建一个新的对象或数组,并将属性值复制到新的对象或数组中。
js
function deepCopy(obj) {
  // 检查是否是基本类型
  if (obj === null || typeof obj !== 'object') {
    return obj;
  }

  // 创建目标对象
  let copy;
  if (Array.isArray(obj)) {
    // 如果是数组,创建一个空数组
    copy = [];
  } else {
    // 如果是对象,创建一个空对象
    copy = {};
  }

  // 遍历源对象的属性
  for (let key in obj) {
    // 这里使用了 hasOwnProperty,是为了过滤掉原型链上的属性,保证只对对象本身的属性进行深拷贝
    if (obj.hasOwnProperty(key)) {
      // 对于每个属性,递归调用深拷贝函数
      copy[key] = deepCopy(obj[key]);
    }
  }

  return copy;
}