# 深克隆

本文不介绍深克隆和浅克隆的区别,若对此有疑惑的朋友请自行查阅资料

另外,本文主要是阐述哈希表的应用,给出的实现并没有完全考虑深克隆中各种可能的问题,如果对此感兴趣的朋友可以自行查阅lodash的源码。

再者,在深拷贝中,我们使用哈希表,需要使用Map或者WeakMap,因为使用对象作为哈希表的话,无法用对象作为key

深拷贝的算法实现思路,最简单的就是递归了,把已经拷贝过的对象和新生成的对象映射加入到哈希表中去,并且递归拷贝的时候,要带上这个哈希表递归。需要注意一点就是,拷贝过程中,一旦新生成的对象产生,就需要建立映射,而不是,等拷贝完成再建立映射,否则就无法区分当前对象是否已经被拷贝了,出现最大调用堆栈报错。

算法实现如下:

/**
 * 使用深度优先深克隆对象
 * @param {Array<any> | object} obj
 * @param { Map<Array<any> | object, Array<any> | object> } map
 * @returns
 */
function deepClone(obj, map = new Map()) {
  // 如果已经拷贝过,则可以直接返回拷贝过的值,主要是为了防止循环引用
  let cloneObj = map.get(obj);
  if (typeof cloneObj !== "undefined") {
    return cloneObj;
  }
  // 初始化拷贝的对象
  cloneObj = Array.isArray(obj) ? [] : {};
  // 建立已经拷贝的引用,不能再开始拷贝属性了再建立拷贝引用,否则将会导致递归最大调用栈的问题发生
  map.set(obj, cloneObj);
  // 对拷贝对象挨个赋值
  for (let prop in obj) {
    // 遇到对象,则递归拷贝
    if (obj[prop] instanceof Object) {
      cloneObj[prop] = deepClone(obj[prop], map);
      // 拷贝完成后,还要将其加入引用Map中去
      map.set(obj[prop], cloneObj[prop]);
    } else {
      cloneObj[prop] = obj[prop];
    }
  }
  return cloneObj;
}
ON THIS PAGE