直接调用 obj.hasOwnProperty(prop) 有风险,因对象自身或原型链上的 hasOwnProperty 可能被篡改;应使用 Object.prototype.hasOwnProperty.call(obj, prop) 或 ES2022 的 Object.hasOwn(obj, prop) 确保安全。

直接用 obj.hasOwnProperty(prop) 有风险——当对象自身覆盖了 hasOwnProperty 方法(比如被恶意赋值为 false 或函数),或原型链上存在同名污染(如 Object.prototype.hasOwnProperty = () => false),检测就会失效。安全做法是「借用」原生 Object.prototype.hasOwnProperty,并通过 call 显式绑定目标对象。
为什么不能直接调用 obj.hasOwnProperty?
因为该方法可能被篡改:
- 对象自身定义了
hasOwnProperty: false,调用时抛TypeError或返回错误结果 - 原型链上的
Object.prototype.hasOwnProperty被重写(原型链投毒),导致所有对象的自有属性检测失真 - 空对象字面量
{}若继承自被污染原型,也会受影响
正确姿势:用 Object.prototype.hasOwnProperty.call()
固定使用原生方法,并把待检测对象作为 this 绑定:
const hasOwn = Object.prototype.hasOwnProperty.call(obj, prop);
这样绕过了对象自身的 hasOwnProperty 属性,也不依赖原型链上是否被污染——因为 Object.prototype.hasOwnProperty 是一个稳定、不可枚举、不可配置的原生函数(除非显式用 Object.defineProperty 强行篡改,但那是极端场景)。
更健壮的封装建议
可封装成工具函数,同时处理 null/undefined 边界情况:
function hasOwnProp(obj, prop) {
if (obj == null) return false;
return Object.prototype.hasOwnProperty.call(obj, prop);
}
或者用 Object.hasOwn()(ES2022+ 推荐):
- 它是
Object.prototype.hasOwnProperty.call()的标准化替代,专为防投毒设计 - 不依赖原型链,内部直接访问内部槽 [[OwnPropertyKeys]]
- 兼容性注意:Node.js ≥16.9 / Chrome ≥93 / Firefox ≥94+
实际检测示例对比
假设发生原型链投毒:
Object.prototype.hasOwnProperty = () => true; // 恶意覆盖
const obj = { a: 1 };
-
obj.hasOwnProperty('b')→true(错误!) -
Object.prototype.hasOwnProperty.call(obj, 'b')→false(正确) -
Object.hasOwn(obj, 'b')→false(正确,且更简洁)

















