You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何__proto__默认隐藏但JSON.parse可显示?如何让JSON.stringify输出它?

解决方案:让__proto__作为普通属性被序列化

直接在对象字面量中使用__proto__(无论带不带引号)都会被JS引擎当作设置对象原型的特殊语法,而非添加普通属性——这就是console.log(x)显示{}、JSON.stringify(x)输出{}的核心原因:__proto__并没有被当作对象的自有可枚举属性,而是用来修改原型链了。

要让__proto__成为普通可枚举属性,从而被JSON.stringify正确序列化,有以下几种可行方法:

方法1:用Object.defineProperty显式定义属性

通过Object.defineProperty可以精确控制属性特性,强制将__proto__定义为可枚举的自有属性:

const x = {};
Object.defineProperty(x, '__proto__', {
  value: { value: 1 },
  enumerable: true, // 必须设为true,否则JSON.stringify会忽略该属性
  writable: true,
  configurable: true
});

console.log(x); // 输出 { __proto__: { value: 1 } }
JSON.stringify(x); // 输出 '{"__proto__": {"value": 1}}'

方法2:创建无原型对象并直接赋值

用Object.create(null)生成完全脱离原型链的对象,此时__proto__不再是特殊的访问器属性,而是普通可写属性:

const x = Object.create(null);
x.__proto__ = { value: 1 };

console.log(x); // 输出 { __proto__: { value: 1 } }
JSON.stringify(x); // 输出 '{"__proto__": {"value": 1}}'

方法3:用Object.assign复制属性

如果需要基于已有对象扩展,可使用Object.assign,但要确保源对象的__proto__是普通属性(比如通过前两种方法创建的对象):

// 先创建一个__proto__为普通属性的源对象
const protoSource = Object.create(null);
protoSource.__proto__ = { value: 1 };

const x = Object.assign({}, protoSource);

console.log(x); // 输出 { __proto__: { value: 1 } }
JSON.stringify(x); // 输出 '{"__proto__": {"value": 1}}'

原理补充

普通对象继承自Object.prototype,而Object.prototype上的__proto__是访问器属性(带getter/setter)——当你给普通对象赋值obj.__proto__ = ...时,实际是调用setter修改对象原型,而非添加自有属性。只有当对象无原型(Object.create(null)),或通过Object.defineProperty显式定义时,__proto__才会被当作普通属性处理。

内容的提问来源于stack exchange,提问作者karemont

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 15:57:27