javascript class需手动实现序列化与反序列化:通过tojson()方法返回纯数据对象供json.stringify使用,再通过静态fromjson()方法重建实例;支持私有字段、嵌套对象及特殊类型处理。

JavaScript 的 class 本身不自带序列化能力,因为 JSON.stringify() 和 JSON.parse() 无法处理方法、私有字段、原型链或特殊类型(如 Date、RegExp、undefined)。但你可以通过约定 + 手动控制,让 class 实例支持可预测的序列化与反序列化。
序列化:把实例转成纯数据对象(JSON 可兼容)
关键是在 class 中提供一个 toJSON() 方法。当 JSON.stringify() 遇到该方法时,会自动调用它,并用其返回值代替原对象:
- 只返回需要持久化的公共属性(排除函数、Symbol、私有字段)
- 对特殊值做预处理(例如把
Date转成 ISO 字符串) - 不依赖
this.constructor或原型信息——JSON 里没有这些
示例:
class User {
constructor(name, birthDate, role = 'user') {
this.name = name;
this.birthDate = new Date(birthDate);
this.role = role;
// 下面这些不会被序列化
this._id = Math.random();
this.greet = () => `Hello, ${this.name}`;
}
<p>toJSON() {
return {
name: this.name,
birthDate: this.birthDate.toISOString(),
role: this.role
};
}
}</p><p>const user = new User('Alice', '1990-05-12');
console.log(JSON.stringify(user));
// → {"name":"Alice","birthDate":"1990-05-12T00:00:00.000Z","role":"user"}</p>
反序列化:从 JSON 字符串重建 class 实例
JSON.parse() 只返回普通对象,所以你需要额外步骤来“升级”为 class 实例:
- 用
JSON.parse(str, reviver)的reviver参数识别特定结构,然后 new 实例 - 或更常见:先解析,再手动构造新实例(推荐,逻辑清晰、可控性强)
- 避免在 reviver 中直接修改原对象,尤其涉及嵌套或循环引用时容易出错
推荐写法(显式构造):
class User {
// ... 同上 constructor 和 toJSON
<p>static fromJSON(jsonStr) {
const data = JSON.parse(jsonStr);
return new User(
data.name,
data.birthDate,
data.role
);
}
}</p><p>const json = '{"name":"Bob","birthDate":"2000-01-01T00:00:00.000Z","role":"admin"}';
const user2 = User.fromJSON(json); // ✅ 得到真正的 User 实例
console.log(user2 instanceof User); // true
console.log(user2.greet()); // "Hello, Bob"</p>
进阶:支持私有字段与嵌套对象
如果 class 使用了私有字段(#field),toJSON() 仍可访问它们(只要在 class 内部定义),但需注意:
- 私有字段不能直接暴露给外部,应在
toJSON()中做映射或脱敏 - 若属性本身是另一个可序列化的 class 实例,确保它的
toJSON()和fromJSON()也已实现 - 避免在序列化中包含计算属性或 getter 返回的动态值(除非你明确希望保存快照)
例如嵌套场景:
class Address {
constructor(city, zip) {
this.city = city;
this.zip = zip;
}
toJSON() { return { city: this.city, zip: this.zip }; }
static fromJSON(json) { return new Address(json.city, json.zip); }
}
<p>class User {
constructor(name, address) {
this.name = name;
this.address = address;
}
toJSON() {
return {
name: this.name,
address: this.address?.toJSON() // 递归序列化
};
}
static fromJSON(json) {
return new User(
json.name,
json.address ? Address.fromJSON(json.address) : null
);
}
}</p>
注意事项与边界情况
以下情况需特别留意,否则容易导致序列化/反序列化失真:
-
函数和方法:永远不进 JSON,不要试图存
toString()后再eval—— 安全风险高且不可靠 -
undefined / NaN / Infinity:JSON 会静默丢弃或转为
null,建议在toJSON()中统一处理 - Date / RegExp / Map / Set:需显式转成字符串或数组结构,反序列化时再还原
-
循环引用:
JSON.stringify()直接报错,可用第三方库(如flatted)或提前检测剔除











