登录
首页 >  文章 >  前端

JSON 方法深拷贝后丢失原始类方法的原因,主要在于 JSON 的序列化与反序列化机制。以下是详细解释:一、JSON 的工作原理JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它本身是纯数据格式,不包含任何函数或方法。因此,当使用 JSON.stringify() 和 JSON.parse() 进行深拷贝时,实际上只是对对象的属性值进行了复制,而不会保留

时间:2026-05-13 18:48:41 212浏览 收藏

JSON深拷贝看似简单,实则是一场“数据降级”——它只保留对象的可枚举自有属性值,彻底剥离构造函数、原型链、方法、getter/setter、私有字段等所有行为与类型语义,最终生成的只是一个以Object.prototype为唯一原型的纯数据对象;因此,无论原始对象多么复杂,经过JSON.stringify再JSON.parse后,它就不再是那个会说话、会继承、有身份的实例,而只是一个沉默的、扁平的、无方法的“数据快照”,这也是为什么你在拷贝后突然发现greet()不见了、this.constructor失效了、甚至整个类的行为逻辑荡然无存的根本原因。

如何理解 原型丢失问题:为什么 JSON 方法深拷贝后的实例会失去原始类的方法

JSON 方法深拷贝后的实例失去原始类的方法,根本原因在于 JSON.stringify 只序列化可枚举的自有属性值,完全不保留构造函数、原型链和任何行为逻辑。它本质上是“数据快照”,不是“对象复刻”。

原型丢失的本质:从对象到纯数据的降级

JavaScript 中,一个由类(如 class Person)创建的实例,其方法并不存储在实例自身上,而是通过 [[Prototype]] 链委托给 Person.prototype。而 JSON.stringify 的规则是:

  • 只遍历对象自身的、可枚举的属性(Object.keys() 范围)
  • 忽略所有不可枚举属性(包括 constructor__proto__ 等)
  • 不读取、不记录、不还原原型链上的任何内容
  • 最终输出的只是键值对组成的字符串,没有类型、没有构造器、没有继承关系

所以 JSON.parse() 还原出来的,永远是一个以 Object.prototype 为唯一原型的普通对象——它和原始类再无血缘关系。

一个直观对比示例

假设有如下类:

class User {
  constructor(name) {
    this.name = name;
  }
  greet() {
    return `Hello, ${this.name}`;
  }
}
const u1 = new User('Alice');

此时 u1.greet() 能调用,是因为 u1.__proto__ === User.prototype

执行深拷贝:

const u2 = JSON.parse(JSON.stringify(u1));

结果 u2 是:

  • 一个普通对象:{ name: "Alice" }
  • u2.__proto__ === Object.prototype(不是 User.prototype
  • typeof u2.greetundefined,调用会报错

为什么不能靠“赋值 prototype”修复?

有人尝试手动补原型:u2.__proto__ = User.prototype。这看似可行,但存在风险:

  • 违反了现代 JavaScript 对 __proto__ 的限制(非标准、已废弃)
  • 若原始类依赖 this.constructor 或私有字段(#field),仍无法恢复
  • 多个实例共享同一原型,可能引发意外状态污染
  • 无法还原静态方法、getter/setter、Symbol 属性等高级特性

真正保留原型的替代方案

如果必须保留类结构和方法,就不能依赖 JSON 序列化。可行路径有:

  • 使用 structuredClone():现代浏览器支持,能保留 DateMapSet 等,但依然不保留函数和原型(和 JSON 方法一样)
  • 类自带克隆方法:在类中定义 clone(),显式构造新实例并复制关键属性
  • 构造函数重建:先获取原对象构造器(obj.constructor),再用 new obj.constructor(...) 创建,并逐个赋值自有属性
  • 第三方库(如 lodash.cloneDeepWith):支持自定义克隆逻辑,可注入构造器处理逻辑

总之,JSON 深拷贝是“去类型化”的过程,适合 DTO、配置、表单数据等纯数据场景;一旦涉及行为、继承或运行时类型语义,就必须换更精确的克隆策略。

以上就是《JSON 方法深拷贝后丢失原始类方法的原因,主要在于 JSON 的序列化与反序列化机制。以下是详细解释:一、JSON 的工作原理JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它本身是纯数据格式,不包含任何函数或方法。因此,当使用 JSON.stringify() 和 JSON.parse() 进行深拷贝时,实际上只是对对象的属性值进行了复制,而不会保留方法。例如:const obj = { name: 'Alice', sayHello: function() { console.log('Hello'); } }; const str = JSON.stringify(obj); // 只会保存 name 属性,sayHello 方法被忽略 const newObj = JSON.parse(str); console.log(newObj.sayHello); // 输出:undefined二、为什么方法会被丢失?JSON 不支持函数:JSON 标准中只定义了基本数据类型(字符串、数字、布尔、数组、对象、null),没有函数类型。序列化过程中自动过滤掉函数:JSON.stringify() 在处理对象时,如果遇到函数,会将其忽略或转换为 null。反序列化无法恢复函数:JSON.parse() 只能将 JSON 字符串还原为普通对象,无法重建函数。三》的详细内容,更多关于的资料请关注golang学习网公众号!

资料下载
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>