真正可靠的深拷贝需三阶段解耦:探测类型与循环引用、构造目标实例、用object.getownpropertydescriptors精确赋值并保留描述符;支持handlers钩子定制策略、weakmap处理循环引用、proxy安全克隆。

直接用 JSON.parse(JSON.stringify(obj)) 或简单递归无法满足真实场景:循环引用会报错、Date/RegExp/Map/Set 丢失类型、getter/setter 和属性描述符(如 writable、enumerable、configurable)完全丢失,更别说按需定制克隆逻辑。一个真正可靠的深拷贝框架,必须分层控制——底层处理对象图遍历与循环引用,中层保留元信息,上层暴露策略钩子。
核心设计:三阶段解耦架构
把拷贝过程拆成可插拔的三步:
- 探测阶段:识别值类型(原始值、内置对象、函数、自定义类、循环引用),决定是否进入克隆流程
-
构造阶段:创建目标实例(如
new target.constructor()或Object.create(Object.getPrototypeOf(obj))),不赋值
赋值阶段:遍历源对象所有自有属性(含不可枚举),读取完整
PropertyDescriptor,在目标上用 Object.defineProperty 精确还原
保留属性描述符的关键实现
不能只用 for...in 或 Object.keys() ——它们跳过不可枚举属性,且不提供描述符。必须用 Object.getOwnPropertyDescriptors() 获取全部自有属性元信息,再逐个定义:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
const descriptors = Object.getOwnPropertyDescriptors(source);
for (const [key, desc] of Object.entries(descriptors)) {
// 若 desc.value 是对象,递归拷贝;若 desc.get 是函数,原样保留(或按策略包装)
const clonedDesc = {
...desc,
value: isPlainObject(desc.value) ? clone(desc.value, options) : desc.value,
get: typeof desc.get === 'function' ? desc.get : undefined,
set: typeof desc.set === 'function' ? desc.set : undefined
};
Object.defineProperty(target, key, clonedDesc);
}
支持自定义克隆策略的钩子机制
通过 options.handlers 注册类型处理器,优先级高于默认逻辑:
- 返回
undefined:交由框架默认处理 - 返回
null:跳过该属性(用于过滤敏感字段) - 返回任意值:直接作为该属性的克隆结果(例如把
Date转成时间戳字符串)
示例:将所有 URL 实例转为字符串,同时让 HTMLCanvasElement 浅拷贝(仅复制引用):
const result = deepClone(obj, {
handlers: {
URL: (url) => url.toString(),
HTMLCanvasElement: (canvas) => canvas // 不递归,直接返回原引用
}
});
循环引用与代理对象的安全处理
用 WeakMap 缓存已克隆对象对(source → target),在探测阶段查表。遇到重复源对象,直接返回缓存目标,避免无限递归。对 Proxy 对象,不尝试解包其内部目标(因 target 属性不可访问),而是调用 Proxy.revocable 创建新代理,并将原 handler 浅拷贝后传入——保持拦截行为一致,但隔离状态。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










