json.parse(json.stringify(obj))深拷贝会丢失原型链,因其仅序列化可枚举自有属性,忽略函数、symbol、构造器及原型信息;反序列化后对象__proto__恒指向object.prototype,导致instanceof失效、方法调用报错。

使用 JSON.parse(JSON.stringify(obj)) 进行深拷贝后,新对象的原型链会被重置为 Object.prototype,原始对象的自定义原型、构造函数信息和原型方法全部丢失。
为什么原型链会丢失
JSON 格式仅支持基本数据类型(字符串、数字、布尔值、null、数组、纯对象),不支持函数、undefined、Symbol、Date、RegExp、Map、Set、Promise 等。序列化过程只保留可枚举的自有属性值,所有原型上的属性和方法都被忽略。反序列化时,JavaScript 总是用 {} 创建新对象,因此其 [[Prototype]] 指向 Object.prototype,与原对象无关。
验证原型链变化的方法
- 用
obj.constructor === OriginalConstructor检查构造函数是否一致 —— JSON 拷贝后结果为false - 用
obj instanceof OriginalConstructor判断实例关系 —— JSON 拷贝后结果为false - 用
Object.getPrototypeOf(obj) === OriginalConstructor.prototype对比原型 —— JSON 拷贝后结果为false - 调用原型上定义的方法(如
obj.customMethod())会报TypeError: obj.customMethod is not a function
哪些对象类型特别容易出问题
以下类型的对象经 JSON 拷贝后不仅丢失原型,还会发生数据失真:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- Date 对象:变成 ISO 字符串,再解析为普通字符串,不再是 Date 实例
-
RegExp 对象:变成空对象
{}或字符串形式(取决于实现),无法执行正则操作 - Map / Set:直接被忽略或转为空对象,键值对信息完全丢失
- 带有 getter/setter 的对象:只保留当前取值结果,访问器属性本身不被序列化
-
循环引用对象:
JSON.stringify直接抛出TypeError
替代方案建议
若需保留原型链和特殊类型,应避免 JSON 方案,改用:
- structuredClone()(现代浏览器 & Node.js 17.0+):支持 Map、Set、Date、RegExp、ArrayBuffer 等,保留原型链(对普通对象有效,但对自定义类实例仍不保留 constructor)
- 第三方库如 lodash.cloneDeep():通过递归遍历和类型判断重建结构,对大多数场景兼容性好
-
手动实现或定制序列化逻辑:针对特定类提供
toJSON()和静态fromJSON()方法
不复杂但容易忽略:只要拷贝后需要调用原型方法或依赖 instanceof 判断,就不能用 JSON 方法。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










