手动实现高效深拷贝的关键在于引用追踪,使用WeakMap缓存对象与副本映射,避免循环引用和重复拷贝;WeakMap因支持对象键、弱引用、O(1)查找成为首选;需在创建副本后立即注册缓存,并仅对引用类型进行追踪处理。

手动实现高效深拷贝,关键不在“递归”本身,而在于如何准确识别并跳过重复引用——也就是引用追踪。核心是用 WeakMap 做缓存映射,提前拦截循环结构,避免无限递归和重复拷贝。
为什么 WeakMap 是引用追踪的首选
WeakMap 能以原始对象为键,且不阻止垃圾回收,既安全又轻量。它天然支持“对象地址 → 已拷贝副本”的一对一映射,正是追踪引用的底层基础。
- 键必须是对象(正好匹配我们要追踪的目标)
- 不会造成内存泄漏(弱引用特性)
- 查找时间复杂度 O(1),比普通 Map 或数组遍历快得多
引用追踪的正确插入时机
不是等递归到底层才存,而是一创建副本就立即注册。这样后续无论从哪个路径再次访问该对象,都能立刻命中缓存,直接返回已生成的副本。
- 先判断是否已在 WeakMap 中:有则直接返回对应副本
- 若无,立刻新建空容器([] 或 {}),并立即将原对象→新容器写入 WeakMap
- 再递归填充属性——此时即使遇到自身引用,也能被拦截
配合类型判断,避免误判“可追踪对象”
并非所有值都需要追踪。只有真正的引用类型(Object、Array、Date、RegExp、Map、Set 等)才可能形成循环或需深度处理;基本类型(string、number、boolean、null、undefined)和 Symbol 直接返回即可。
立即学习“Java免费学习笔记(深入)”;
-
typeof obj !== 'object' || obj === null→ 直接返回(覆盖 null 和基本类型) -
obj instanceof Date→ new Date(obj.getTime()) -
obj instanceof RegExp→ new RegExp(obj.source, obj.flags),并同步 lastIndex -
obj instanceof Map / Set→ 新建对应实例,逐项 deepClone 键与值
一个精简但完整的引用追踪骨架
以下代码保留了核心逻辑,去掉了冗余分支,适合嵌入已有工具链:
function deepClone(obj, cache = new WeakMap()) {
if (obj === null || typeof obj !== 'object') return obj;
if (cache.has(obj)) return cache.get(obj);
let clone;
if (obj instanceof Date) clone = new Date(obj.getTime());
else if (obj instanceof RegExp) clone = new RegExp(obj.source, obj.flags);
else if (obj instanceof Array) clone = [];
else if (obj instanceof Map) clone = new Map();
else if (obj instanceof Set) clone = new Set();
else clone = Object.create(Object.getPrototypeOf(obj));
cache.set(obj, clone);
if (obj instanceof Array || obj instanceof Object) {
for (const key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
clone[key] = deepClone(obj[key], cache);
}
}
} else if (obj instanceof Map) {
obj.forEach((v, k) => clone.set(deepClone(k, cache), deepClone(v, cache)));
} else if (obj instanceof Set) {
obj.forEach(v => clone.add(deepClone(v, cache)));
}
return clone;
}


















