json.stringify仅序列化对象自身可枚举属性,忽略原型链及不可枚举属性;若需包含特定数据,应挂载到实例或通过tojson()方法自定义。

JSON.stringify 不会序列化 prototype 原型对象上的属性或方法,这是它的默认行为,无需额外操作 —— 它本来就不处理原型链。
JSON.stringify 只遍历自身可枚举属性
它只检查对象自身的、可枚举的(enumerable: true)属性,完全跳过原型链上的任何内容。即使你在 Object.prototype 上添加了属性,也不会出现在结果中。
例如:
function Person(name) {
this.name = name;
}
Person.prototype.age = 25; // 原型属性
Person.prototype.sayHi = function() { return 'Hi'; }; // 原型方法
const p = new Person('Alice');
console.log(JSON.stringify(p)); // {"name":"Alice"}
// age 和 sayHi 都没出现
手动添加的不可枚举属性也被忽略
即使你用 Object.defineProperty 在实例上定义了不可枚举属性,JSON.stringify 同样跳过它:
Object.defineProperty(p, 'id', {
value: 1001,
enumerable: false
});
console.log(JSON.stringify(p)); // 还是 {"name":"Alice"}
想让某些“原型级”数据参与序列化?得显式挂到实例上
如果业务上需要某个字段总是被序列化(比如统一的 type 标识),不要依赖原型,而应在构造时写入实例:
- 在构造函数里赋值:
this.type = 'person'; - 使用 class 的 constructor 初始化:
this.type = 'person'; - 或重写
toJSON()方法来自定义输出结构
例如:
class Person {
constructor(name) {
this.name = name;
this.type = 'person'; // 实例自有属性 → 会被序列化
}
toJSON() {
return { name: this.name, type: this.type, createdAt: new Date().toISOString() };
}
}
console.log(JSON.stringify(new Person('Bob')));
// {"name":"Bob","type":"person","createdAt":"2024-05-..."}
注意:toJSON 方法优先级最高
如果对象有 toJSON() 方法,JSON.stringify 会直接调用它,并用其返回值作为序列化输入 —— 此时原型上的属性依然不自动进入,但你可以主动把需要的内容组装进去。
这个方法是可控的入口,适合封装序列化逻辑,也避免误触原型。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











