自定义深拷贝函数需识别特殊类型并分情况处理:date、regexp、map/set、typedarray、error等需显式构造;用weakmap防循环引用;保留原型链与不可枚举属性;支持自定义类及第三方结构扩展。

自定义深拷贝函数处理特殊类型,核心在于识别类型、分情况构造新实例、递归复制状态,并统一管理循环引用。不能靠 JSON 方法,也不能只递归普通对象。
识别并分别处理 Date、RegExp 等内置特殊对象
这些类型无法通过 JSON.stringify 保留,也不能用 Object.assign 或展开运算符还原构造信息。需显式判断类型后调用对应构造逻辑:
-
Date:用
new Date(original.getTime())或new Date(original.toString()),确保时区和毫秒精度一致 -
RegExp:用
new RegExp(original.source, original.flags),注意global、ignoreCase等 flag 必须显式传入 - Map / Set:新建实例后遍历原结构,对键值都做深拷贝(Map 的键也可能是对象,不能忽略)
-
TypedArray(如
Uint8Array):用original.constructor(original)或基于buffer和byteOffset构造 -
Error:通常新建
new Error(original.message),若需保留堆栈或自定义属性,要额外提取
用 WeakMap 防止循环引用死循环
无论对象是否特殊,只要可能被多处引用(比如某个 Map 被嵌套在多个层级中),就必须缓存已处理的源对象与副本映射:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 每次进入拷贝前,先查
WeakMap.has(original);命中则直接返回缓存副本 - 对 Date、RegExp 这类不可变对象,缓存非必需,但为统一逻辑建议统一纳入
- Map、Set、普通 Object、Array 等可变容器必须缓存,否则递归会无限展开
保留原型链和不可枚举属性
如果原始对象是继承自内置类(如自定义 MyDate extends Date)或手动添加了不可枚举属性,简单重建会丢失这些信息:
- 用
Object.create(Object.getPrototypeOf(original))创建目标对象,继承原始原型 - 用
Object.getOwnPropertyDescriptors(original)获取全部属性描述符(含enumerable: false、getter/setter) - 对每个 descriptor 的
value,如果是对象就递归深拷贝;get/set函数则直接复制(除非你明确需要重绑定) - RegExp 和 Date 默认无自定义不可枚举属性,但如果手动加过(如
Object.defineProperty(reg, 'meta', {value: 1, enumerable: false})),也要一并处理
支持自定义类或第三方结构的扩展点
实际项目中常遇到 User 类、Axios 实例、React 元素等非标准结构。可在拷贝函数中预留类型检查分支:
- 检查
original instanceof User,然后手动 new 并赋值关键字段 - 对已知第三方类(如
moment对象),按其文档推荐方式克隆(如original.clone()) - 若某类型允许浅拷贝(如大型只读配置对象),可在判断后直接返回
original,提升性能
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










