避开原型污染的关键是使用 Object.hasOwn() 或 Object.prototype.hasOwnProperty.call(),而非 in、obj.hasOwnProperty() 或 obj.key !== undefined;前者绕过原型链直接检测自有属性,后者易受污染或误判。

避开原型污染的关键,是不用对象自身的方法去查自身属性——因为那个方法本身可能已被篡改或覆盖。真正安全的做法,是绕过对象的原型链,直接调用原始、未被污染的检测逻辑。
优先用 Object.hasOwn() —— 现代环境的首选
Object.hasOwn(obj, 'key') 是 ES2022 标准引入的静态方法,专为解决原型污染而设计:
- 它不依赖 obj 的任何原型方法,哪怕 obj 是
Object.create(null)或hasOwnProperty被删/重写,也能正常工作 - 语义明确:只查自有属性,不查原型链,也不受
enumerable影响 - 性能优于
Object.keys().includes(),且不生成临时数组 - 主流环境(Chrome 93+、Firefox 91+、Safari 16.4+、Node.js 16.9+)已原生支持
兼容老环境时,用 call 方式兜底
若需支持 IE 或早期运行时,不能写 obj.hasOwnProperty('key'),而应固定调用原始方法:
-
正确写法:
Object.prototype.hasOwnProperty.call(obj, 'key') - 这跳过了对象自身的属性查找路径,直接绑定到原始
hasOwnProperty实现 - 即使
obj是空对象、null原型,或hasOwnProperty被赋值为字符串/函数/undefined,也不会报错
别用 in 操作符查“自有属性”
'key' in obj 会沿整个原型链查找,天然暴露在污染风险下:
- 如果
Object.prototype.key = true被恶意注入,'key' in {}就会返回true,造成误判 - 它适合判断“能否访问到”,但不适合判断“是否对象自己定义了”,语义和场景不匹配
- 若真需要检查可访问性(含继承),
Reflect.has(obj, 'key')更函数式,但同样无法规避原型污染
彻底避开值判断陷阱
obj.key !== undefined 或 if (obj.key) 这类写法既不安全也不准确:
- 属性存在但值为
undefined→ 判定为“不存在” - 属性有 getter → 触发副作用,甚至抛错(如访问
null上的属性) - 根本不是存在性检测,而是值判断,逻辑错位

















