深拷贝类实例时原型丢失,因json.stringify仅提取自身可枚举属性,忽略原型链;structuredclone是现代首选方案,能完整保留原型链,但不支持函数、symbol等;旧环境需用object.create还原继承结构,并手动处理内置类型。

深拷贝类实例时原型丢失,本质是拷贝过程切断了对象与构造函数原型的委托关系——方法还在原型上,但新对象找不到它了。
为什么 JSON 拷贝必然丢原型
JSON.stringify 只提取对象自身的可枚举属性,完全忽略 constructor、__proto__、不可枚举属性和整个原型链。还原后得到的是纯 plain object,其 [[Prototype]] 指向 Object.prototype,不再关联原始类。结果就是:instanceof 失效、原型方法调用报错、getter/setter 不触发。
structuredClone 是现代首选方案
它原生支持 Date、RegExp、Map、Set 等内置类型,并完整保留自定义类实例的原型链(前提是构造器可访问、非闭包私有)。一行代码即可:
const copy = structuredClone(originalInstance);
验证方式必须包含三重断言:
- copy instanceof OriginalClass → true
- typeof copy.someMethod === 'function' → true
- Object.getPrototypeOf(copy) === OriginalClass.prototype → true
注意:它不支持函数、Symbol、undefined、WeakMap/WeakSet —— 这是规范限制,不是缺陷。
旧环境需手动重建原型
当无法使用 structuredClone(如 IE 或 Node.js
- 用 Object.create(obj.constructor.prototype) 创建新实例,而非 {} 或 new obj.constructor()
- 对 Date、RegExp 等内置类型,显式调用对应构造器:new Date(obj)、new RegExp(obj)
- 避免直接赋值 copy.__proto__ = obj.__proto__ —— 非标准、严格模式下可能失败,且对冻结对象无效
- 若类有静态属性或 Symbol 成员,需通过 Object.getOwnPropertyDescriptors 同步到新实例或构造器
从设计源头降低风险
与其反复修补拷贝逻辑,不如让对象更“可拷贝”:
- 用鸭子类型代替 instanceof:检查 obj.getDate 是否为函数,而非 obj instanceof Date
- 核心逻辑抽成纯函数,接收原始数据(时间戳、正则字符串)而非实例
- 为自定义类提供 toJSON() 和静态 fromJSON() 方法,控制序列化路径
- 不在原型上挂载可变状态或闭包变量,防止拷贝后行为错乱
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











