检测对象属性存在性需区分自身属性与原型链属性:用in或Reflect.has查整个原型链;用Object.hasOwn(推荐)、hasOwnProperty或call方式查自身属性;用propertyIsEnumerable结合getPrototypeOf确认是否来自特定构造函数原型。

要检测一个对象是否存在由特定构造函数定义的属性,关键在于区分“自身属性”和“原型链上的属性”——因为构造函数通常把共享属性放在 prototype 上,而实例属性写在 this 上。你需要明确:是查实例自己有的,还是查它从构造函数原型继承来的?
查构造函数原型上定义的属性(继承来的)
这类属性不会出现在对象自身,但可通过原型链访问。适合判断是否“属于该类的设计能力”,比如方法或默认配置。
- 用
in运算符:检查属性是否存在于对象或其整个原型链中 - 用
Reflect.has(obj, key):行为与in完全一致,语法更函数式 - 注意:
'toString' in {}返回true,因为它来自Object.prototype
查对象自身是否拥有该属性(非继承)
如果属性是构造函数内部用 this.xxx = ... 显式赋值的,就属于实例自身。这时要用不依赖原型链的方法:
-
obj.hasOwnProperty('prop'):最常用,但若对象重写了该方法可能出错 -
Object.prototype.hasOwnProperty.call(obj, 'prop'):更安全,绕过可能被覆盖的实例方法 -
Object.hasOwn(obj, 'prop'):ES2022 新增,推荐替代hasOwnProperty,语义清晰且无覆盖风险
查该属性是否来自某个特定构造函数的 prototype
有时你需要确认属性确实定义在某构造函数的原型上,而不是更上层(如 Object.prototype)。可以这样定位:
- 先用
obj.propertyIsEnumerable('prop')判断是否可枚举(多数prototype属性默认可枚举) - 再用
Object.getPrototypeOf(obj) === Constructor.prototype确认直接原型匹配 - 或者遍历原型链:
let p = obj; while (p && !(p.constructor === Constructor)) p = Object.getPrototypeOf(p);,再检查p是否有该属性
避开常见陷阱
别用 obj.prop !== undefined 或 if (obj.prop) 来判断存在性——如果属性值恰好是 null、0、false 或 '',逻辑会误判;如果属性值本身就是 undefined,更是完全失效。


















