CodeWalk

手写深拷贝(WeakMap解决循环引用)

作者:我还是少年 · 2026-05-30 12:55

请手写一个完整的深拷贝函数,支持对象、数组、Date、RegExp、Map、Set,并使用WeakMap解决循环引用。

回答

我还是少年

function deepClone(obj, hash = new WeakMap()) {
  if (obj === null || typeof obj !== 'object') return obj;
  if (hash.has(obj)) return hash.get(obj);
  
  if (obj instanceof Date) return new Date(obj);
  if (obj instanceof RegExp) return new RegExp(obj);
  if (obj instanceof Map) {
    const map = new Map();
    hash.set(obj, map);
    obj.forEach((v, k) => map.set(deepClone(k, hash), deepClone(v, hash)));
    return map;
  }
  if (obj instanceof Set) {
    const set = new Set();
    hash.set(obj, set);
    obj.forEach(v => set.add(deepClone(v, hash)));
    return set;
  }
  
  const proto = Object.getPrototypeOf(obj);
  const cloneObj = Object.create(proto);
  hash.set(obj, cloneObj);
  
  for (const key of Reflect.ownKeys(obj)) {
    const desc = Object.getOwnPropertyDescriptor(obj, key);
    if (desc && desc.enumerable) {
      cloneObj[key] = deepClone(obj[key], hash);
    }
  }
  return cloneObj;
}

const obj = { a: 1, b: { c: 2 }, d: [1, 2] };
obj.self = obj;
const cloned = deepClone(obj);
console.log(cloned.self === cloned);

注意:WeakMap key为弱引用,深拷贝完成后可被GC回收,避免内存泄漏。