深拷贝的核心难点在于处理原生及自定义类型,关键在于提供可插拔的 symbol.for('deepclonehandler') 类型处理器机制,结合缓存、递归与类型分发实现健壮深拷贝。

深拷贝的核心难点不在基础对象和数组,而在处理 Date、RegExp、Map、Set、TypedArray 等原生类型,以及支持未来新增的自定义类型。关键不是“写全所有类型”,而是提供可插拔的类型处理器机制。
用 Symbol 作为类型注册入口
利用 Symbol.for('deepCloneHandler') 作为统一扩展点,让任意类型(包括第三方类)自行声明如何被深拷贝:
- 内置类型如 Date、RegExp 可预先注册默认处理器
- 用户定义的类只需在原型上设置该 Symbol 方法,返回其深拷贝逻辑
- 避免 instanceof 或 constructor.name 判断,不依赖具体构造函数名,更健壮
递归 + 缓存 + 处理器分发
主拷贝函数维持一个 WeakMap 缓存(防循环引用),对每个值先查缓存,再根据类型分发:
- 基础类型(null、undefined、string、number、boolean、symbol、bigint)直接返回
- 若值有 Symbol.for('deepCloneHandler'),调用它并传入原始值和当前缓存 Map
- 否则按 Object.prototype.toString.call() 匹配内置类型(如 [object Date]),走预设逻辑
- 普通 plain object 和 array 用递归遍历,每个子项再次进主流程
内置类型预置处理器示例
为常见类型提供开箱即用的支持,且逻辑清晰可替换:
- Date:new Date(obj.getTime())
- RegExp:new RegExp(obj.source, obj.flags)
- Map:new Map([...obj].map(([k, v]) => [clone(k), clone(v)]))
- Set:new Set([...obj].map(v => clone(v)))
- TypedArray:obj.constructor.from(obj)
用户自定义类型轻松接入
无需修改深拷贝库源码,只需在类上声明处理逻辑:
class User {
constructor(name, role) {
this.name = name;
this.role = role;
}
}
User[Symbol.for('deepCloneHandler')] = function (original, cache) {
const cached = cache.get(original);
if (cached) return cached;
const copy = new User(original.name, clone(original.role, cache));
cache.set(original, copy);
return copy;
};
这样,clone(new User('Alice', { level: 2 })) 就能正确处理嵌套和循环引用。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











