JavaScript -- 浅谈深拷贝和浅拷贝

39 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第1天,点击查看活动详情

浅拷贝(shallow copy)

浅拷贝就是拷贝指向对象的指针,意思就是说:拷贝出来的目标对象的指针和源对象的指针指向的内存空间是同一块空间,浅拷贝只是一种简单的拷贝,让几个对象公用一个内存(即指向同一个对象)

换言之,浅拷贝就是指对象复制的时候只复制一层;深拷贝是指复制对象的所有层级。

注意:当拷贝对象只有一层的时候,是深拷贝

在JavaScript中,存在浅拷贝的现象有:

  • Object.assign
  • Array.prototype.slice()
  • Array.prototype.concat()
  • 使用拓展运算符实现的复制

深拷贝 (deep copy)

深拷贝是指源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响,拷贝完成之后,通过这个引用修改其指向的数据,不会影响到原来的数据。

常见的深拷贝方式有:

  • _.cloneDeep()
  • jQuery.extend()
  • JSON.stringify()--这种方式存在弊端,会忽略undefined、symbol和函数
  • 手写循环递归

浅写递归代码

function deepClone(obj, hash = new WeakMap()) {
  if (obj === undefined) return undefined // undefined 的情况
  if (obj === null) return obj; // 如果是null或者undefined我就不进行拷贝操作
  if (obj instanceof Date) return new Date(obj);//日期对象的情况
  if (obj instanceof RegExp) return new RegExp(obj);//正则表达式的情况
  // 可能是对象或者普通的值  如果是函数的话是不需要深拷贝
  if (typeof obj !== "object") return obj;
  // 是对象的话就要进行深拷贝
  if (hash.get(obj)) return hash.get(obj);
  let cloneObj = new obj.constructor();
  // 找到的是所属类原型上的constructor,而原型上的 constructor指向的是当前类本身
  hash.set(obj, cloneObj);
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      // 实现一个递归拷贝
      cloneObj[key] = deepClone(obj[key], hash);
    }
  }
  return cloneObj;
}