__proto__ 不参与 json.stringify 序列化,仅序列化自有可枚举属性;原型污染虽不直接影响 json 输出,但会隐式污染后续所有对象,导致 for...in 等操作意外暴露属性。

__proto__ 属性本身不参与标准对象序列化(如 JSON.stringify()),但它可能间接影响序列化结果——主要通过原型链上可枚举属性的意外暴露、或修改内置原型导致全局行为改变。
JSON.stringify 会忽略 __proto__ 和原型链属性
JSON.stringify() 只序列化对象自身的**可枚举自有属性**,完全不访问 __proto__、prototype 或原型链上的任何内容。即使你手动设置 obj.__proto__.shared = "x",这个值也不会出现在 JSON 字符串中。
- ✅ 安全:原型污染(如篡改
Object.prototype)不会让额外字段进入 JSON 输出 - ⚠️ 注意:如果通过
Object.assign()或展开运算符把原型属性“拷贝”成自有属性,那些属性就会被序列化
__proto__ 赋值可能触发不可见的副作用
在部分旧环境(如早期 Chrome)中,直接写 obj.__proto__ = newProto 会触发内部原型切换,某些引擎曾因此导致:
- 对象内部隐藏类(hidden class)失效,影响 V8 优化路径
- 序列化前若对象刚经历原型变更,极少数情况下
for...in枚举顺序异常(进而影响依赖该顺序的自定义序列化逻辑) - 若新原型含
toJSON()方法,且该方法读取了原型链上的状态,则序列化行为可能间接变化
真正需要警惕的是原型污染带来的“假自有属性”
当攻击者通过 JSON.parse 输入恶意数据并用 __proto__ 注入属性时(如 {"__proto__": {"admin": true}}),虽不会出现在最终 JSON 字符串里,但会影响后续所有对象:
- 后续创建的普通对象(如
{})会继承被污染的admin属性 - 若业务代码用
for...in遍历对象再拼接字符串(非 JSON),就可能把admin当作有效字段输出 - 使用
Object.keys(obj)是安全的(只返回自有属性),但Object.getOwnPropertyNames(obj)仍不含__proto__相关内容
现代替代方案更干净、无遗留风险
避免直接操作 __proto__,改用标准 API 可彻底规避相关隐患:
- 用
Object.create(proto)创建带指定原型的对象(语义清晰、无副作用) - 用
Object.setPrototypeOf(obj, proto)替代赋值(虽仍不推荐频繁调用,但比__proto__更规范) - 序列化前用
Object.hasOwn(obj, key)或Object.getOwnPropertyDescriptors(obj)显式检查属性来源
不复杂但容易忽略:__proto__ 是历史遗留的访问器属性,不是对象状态的一部分;它影响的是运行时行为,而非序列化数据本身。真正要防的,是污染后对“后续所有对象”的隐式干扰。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











