手写深拷贝(WeakMap解决循环引用)
请手写一个完整的深拷贝函数,支持对象、数组、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回收,避免内存泄漏。