最稳妥的方法是 object.prototype.hasownproperty.call(obj, key)。它专为检测对象自身的实例属性设计,不依赖原型链、可枚举性或属性值,且能避免对象自身覆盖 hasownproperty 方法导致的错误。

直接用 Object.prototype.hasOwnProperty.call(obj, key) 最稳妥。它专为检测对象自身的实例属性设计,不关心原型链、不依赖属性是否可枚举,也不受 undefined 值干扰。
只查自己身上的属性(排除继承)
实例属性指的是对象自己拥有的、不是从原型链上继承来的属性。比如:
-
const obj = { name: 'Alice' }→name是实例属性 -
obj.toString是继承自Object.prototype的,不算实例属性
这时不能用 'name' in obj(它会返回 true 即使是继承的),也不能用 obj.name !== undefined(如果 obj.name = undefined 就会误判)。
为什么推荐 hasOwnProperty.call()
避免对象自身覆盖了 hasOwnProperty 方法导致出错。例如:
-
const badObj = { hasOwnProperty: () => false }—— 这样直接调用badObj.hasOwnProperty('x')就失效了 - 而
Object.prototype.hasOwnProperty.call(badObj, 'x')仍能正确工作
其他方法的适用边界
不同场景可以换用,但要注意限制:
-
'key' in obj:能查到继承属性,适合“是否存在(不管哪来的)”的宽松判断 -
Object.keys(obj).includes('key'):只查可枚举的自身属性,不可枚举的(如Object.defineProperty(obj, 'hidden', { value: 1, enumerable: false }))会被漏掉 -
Reflect.has(obj, 'key'):行为等同于in,也是查自身 + 原型链
一句话总结
要确认“这个属性是不是对象自己定义的”,就用 Object.prototype.hasOwnProperty.call(obj, 'key')。它不绕弯、不踩坑,是判断实例属性存在性的标准解法。











