
JSON.stringify() 默认只序列化对象的可枚举(enumerable)自有属性,非枚举属性(如通过 Object.defineProperty 设置 enumerable: false 的属性)会被自动忽略,这是其标准行为,而非 bug。
`json.stringify()` 默认只序列化对象的可枚举(enumerable)自有属性,非枚举属性(如通过 `object.defineproperty` 设置 `enumerable: false` 的属性)会被自动忽略,这是其标准行为,而非 bug。
当你使用 JSON.stringify() 处理对象时,它遵循 ECMAScript 规范:仅遍历并序列化对象自身、且 enumerable === true 的属性。这意味着以下情况的属性均不会出现在最终 JSON 字符串中:
- 使用 Object.defineProperty() 显式设置 enumerable: false 的属性
- Object.prototype 上的继承属性(默认不可枚举)
- getters(除非显式调用并赋值为普通字段)
- Symbol 类型键(即使可枚举,JSON.stringify 也完全忽略)
例如,以下代码输出 {"prop1":"value1"},prop2 消失:
const obj = { prop1: 'value1' };
Object.defineProperty(obj, 'prop2', {
value: 'value2',
enumerable: false, // ? 关键:不可枚举 → 被 stringify 忽略
writable: true,
configurable: true
});
console.log(JSON.stringify(obj)); // {"prop1":"value1"}✅ 解决方案:确保属性可枚举
最直接的方式是将 enumerable 设为 true(这也是数据属性的默认值):
Object.defineProperty(obj, 'prop2', {
value: 'value2',
enumerable: true, // ✅ 显式启用可枚举性
writable: true,
configurable: true
});
console.log(JSON.stringify(obj)); // {"prop1":"value1","prop2":"value2"}⚠️ 注意:不要依赖 JSON.stringify 处理特殊结构
若需强制包含不可枚举属性、getter、Symbol 或循环引用,应使用自定义 replacer 函数或专用序列化工具(如 structuredClone + 自定义序列化逻辑)。例如,通过 replacer 手动注入非枚举属性:
function serializeAll(obj) {
const allKeys = Object.getOwnPropertyNames(obj).concat(
Object.getOwnPropertySymbols(obj)
);
const result = {};
for (const key of allKeys) {
result[key] = obj[key];
}
return JSON.stringify(result);
}? 总结:JSON.stringify 的“丢失”不是缺陷,而是设计使然。排查时优先检查 propertyIsEnumerable() 返回值;生产环境建议统一使用可枚举属性建模,避免隐式依赖非标准序列化行为。


















