json深拷贝丢失原型链,本质是其仅序列化可枚举自有属性,忽略函数、symbol、__proto__等,使new myclass()拷贝后退化为{}→object.prototype,导致方法调用报错;需改用新建实例+复制属性+设置原型的方式保留继承。

深拷贝时丢失原型链,本质是拷贝过程绕过了构造逻辑,只复制了数据属性。要保留原型方法和继承关系,就不能依赖纯序列化(如 JSON.parse(JSON.stringify())),而需重建实例并显式绑定原型。
为什么 JSON 深拷贝会断掉原型链
JSON 标准只支持基本类型、普通对象、数组、字符串化日期等,它完全忽略:
- 函数(包括原型上的方法)
- Symbol 键和值
- undefined、NaN、Infinity
- __proto__、constructor、原型链信息
结果就是:原对象 new MyClass() 的原型链是 obj → MyClass.prototype → Object.prototype;JSON 拷贝后变成一个裸对象 {},原型链退化为 {} → Object.prototype,所有 MyClass.prototype 上的方法调用都会报错。
保留原型链的深拷贝关键做法
核心思路是:**不“序列化还原”,而是“新建实例 + 复制自有属性 + 设置原型”**。
- 判断原对象是否由构造函数创建(
obj.constructor !== Object且obj.constructor存在),若是,优先用new obj.constructor()创建新实例 - 使用
Object.getOwnPropertyNames()和Object.getOwnPropertySymbols()获取所有自有属性(含 Symbol),再递归深拷贝每个值 - 用
Object.setPrototypeOf(newObj, Object.getPrototypeOf(obj))显式设置新对象的原型,比直接赋值__proto__更标准、兼容性更好 - 对
Date、RegExp、Map、Set等内置类型,单独识别并用对应构造器重建(如new Date(obj)),避免降级为普通对象
简易可运行的保留原型深拷贝函数
以下是一个轻量、可落地的实现(不含循环引用处理,如需可加 WeakMap 缓存):
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
function deepCloneWithPrototype(obj) {
if (obj === null || typeof obj !== 'object') return obj;
// 处理 Date、RegExp、Array 等内置类型
if (obj instanceof Date) return new Date(obj);
if (obj instanceof RegExp) return new RegExp(obj.source, obj.flags);
if (Array.isArray(obj)) return obj.map(item => deepCloneWithPrototype(item));
// 创建新实例:优先用原构造器,fallback 到 Object.create
const Constructor = obj.constructor;
const isNewable = typeof Constructor === 'function' && Constructor !== Object;
const clone = isNewable ? new Constructor() : Object.create(Object.getPrototypeOf(obj));
// 复制所有自有属性(含 Symbol)
const props = [...Object.getOwnPropertyNames(obj), ...Object.getOwnPropertySymbols(obj)];
for (const key of props) {
const desc = Object.getOwnPropertyDescriptor(obj, key);
Object.defineProperty(clone, key, {
value: deepCloneWithPrototype(desc.value),
writable: desc.writable,
enumerable: desc.enumerable,
configurable: desc.configurable
});
}
return clone;
}
这样拷贝后的对象能正常调用 obj.sayHello()、obj.toString() 等原型方法,继承关系完整保留。
现代浏览器推荐方案:structuredClone + 补充处理
structuredClone() 原生支持大多数类型(Date、RegExp、Map、Set、嵌套对象等),但仍不支持函数和 Symbol 键,也不保留自定义原型链。
若项目环境支持(Chrome 98+、Firefox 94+、Edge 98+),可组合使用:
- 对无函数/无 Symbol 的纯数据对象,直接用
structuredClone(obj) - 对含原型方法的对象,先提取构造器和原型,再用上面的手写函数;或改用
class+toJSON()/fromJSON()显式约定序列化协议
不复杂但容易忽略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










