深拷贝的方法

124 阅读1分钟

深拷贝

深拷贝指的是将一个对象完整地复制到另一个对象中,即使原始对象中包含了其他对象的引用,也能将其完整地复制过来,使得两个对象在内存中是完全独立的,互不影响。

深拷贝与浅拷贝不同之处在于,浅拷贝只是将原始对象的引用复制给新对象,新对象和原始对象会共享同一个内存空间,对于新对象所做的任何修改都会影响到原始对象。

方法一

const b = JSON.parse(JSON.stringify(a))

此方法有如下缺点:

  1. 不支持 Date, 正则, undefined,函数等引用类型
  2. 不支持对象中的循环引用

方法二

思路:

  1. 使用递归
  2. 判断类型
  3. 检查环
  4. 不拷贝原型上的属性
const deepClone = (a, cache) => {
  if (!cache) {
    cache = new Map(); // 缓存对象的属性,以保证不会重复拷贝
  }

  // 如果不是对象则是原始类型直接返回
  if (a instanceof Object) {
    // 如果缓存中有此属性,则使用缓存的属性,不递归。
    if (cache.get(a)) {
      return cache.get(a);
    }
    let result;
    if (a instanceof Function) {
      // 有 prototype 就是普通函数
      if (a.prototype) {
        result = function () {
          return a.apply(this, args);
        };
      } else {
        result = (...args) => {
          return a.call(undefined, ...args);
        };
      }
    } else if (a instanceof Array) {
      result = [];
    } else if (a instanceof Date) {
      // a - 0 可以将日期变成时间戳
      result = new Date(a - 0);
    } else if (a instanceof RegExp) {
      // a.source 是正则表达式的文本
      // a.flags 是正则表达式的标志
      result = new RegExp(a.source, a.flags);
    } else {
      result = {};
    }
    // 缓存
    cache.set(a, result);
    for (let key in a) {
      if (a.hasOwnProperty(key)) {
        result[key] = deepClone(a[key], cache);
      }
    }
    return result;
  } else {
    return a;
  }
};