深拷贝需递归判断类型、用WeakMap解决循环引用、逐层复制嵌套结构;支持null、基本类型、Date、RegExp、Array等,避免JSON方法的缺陷。

用递归实现深拷贝,核心是判断数据类型、处理循环引用、逐层复制嵌套结构。下面是一个兼顾健壮性与通用性的实现方案。
基础递归逻辑:识别类型并分支处理
深拷贝不能只用 JSON.parse(JSON.stringify(obj)),它会丢失函数、undefined、Symbol、Date、RegExp 等类型,也无法处理循环引用。递归实现需手动区分:
- null 和基本类型(string/number/boolean/bigint/symbol):直接返回,无需拷贝
- 引用类型(Object、Array、Date、RegExp、Map、Set、TypedArray 等):创建新实例,再递归拷贝其属性或元素
-
函数(Function):通常不拷贝(保留原引用),也可选择浅拷贝(如用
obj.constructor.toString()重建,但不可靠)
关键:用 WeakMap 解决循环引用
对象可能嵌套引用自身(如 a.b = a),递归时若不记录已拷贝过的对象,会导致栈溢出。WeakMap 适合做“源对象 → 拷贝后对象”的缓存映射,原因:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 键必须是对象,天然适配引用类型
- 弱引用,不影响垃圾回收,避免内存泄漏
- 在进入递归前先查缓存,命中则直接返回,打断无限递归
支持常见内置对象的完整实现
以下是一个生产可用的简化版(不含 Proxy、不处理 ArrayBuffer 视图等极端情况,但覆盖日常 95% 场景):
立即学习“Java免费学习笔记(深入)”;
function deepClone(obj, cache = new WeakMap()) {
// 处理 null 和基本类型
if (obj === null || typeof obj !== 'object') return obj;
// 检查循环引用
if (cache.has(obj)) return cache.get(obj);
// 处理 Date
if (obj instanceof Date) return new Date(obj.getTime());
// 处理 RegExp
if (obj instanceof RegExp) return new RegExp(obj);
// 处理 Array
if (Array.isArray(obj)) {
const arr = [];
cache.set(obj, arr);
for (let i = 0; i < obj.length; i++) {
arr[i] = deepClone(obj[i], cache);
}
return arr;
}
// 处理普通对象(含 Map、Set 等)
const cloned = Object.create(Object.getPrototypeOf(obj));
cache.set(obj, cloned);
// 遍历自有属性(包括 Symbol 键)
const keys = [...Object.getOwnPropertyNames(obj), ...Object.getOwnPropertySymbols(obj)];
for (const key of keys) {
const desc = Object.getOwnPropertyDescriptor(obj, key);
if (desc && desc.enumerable) {
cloned[key] = deepClone(obj[key], cache);
}
}
return cloned;
}
使用注意和边界说明
- 不拷贝原型链上的属性,只拷贝自有可枚举属性(符合多数预期)
- 保持原对象的构造器原型(
Object.create(...)),所以cloned instanceof Date仍为 true - Map/Set 需额外扩展:可在检测到
obj instanceof Map时新建 Map 并递归 set 键值对;Set 同理 - 函数默认不拷贝(保留引用),如需隔离,可加判断
typeof obj === 'function'并返回新函数(但无法真正“复制”闭包环境)

















