要判断属性是否在直接原型上,需先排除自身属性(!obj.hasownproperty(prop)),再检查直接原型是否自有该属性(object.getprototypeof(obj).hasownproperty(prop));in 操作符因遍历整条原型链而不适用。

要检查一个对象是否直接在其原型链上拥有某个属性(即该属性存在于其直接原型中,而非对象自身,也非更上层的原型),不能只用 in 或 hasOwnProperty() 单独判断——它们分别覆盖“整个原型链”和“仅自身”,但不聚焦于“直接原型”这一层。
确认属性是否定义在直接原型上
核心思路是:先排除自身属性,再确认该属性是否存在于 Object.getPrototypeOf(obj) 中。
- 用
!obj.hasOwnProperty(prop)确保不是自身属性 - 再用
prop in Object.getPrototypeOf(obj)检查是否在直接原型中(注意:in会继续查找该原型的原型链,所以需配合前一步限制层级) - 为严格限定“仅直接原型”,可进一步比对:
Object.getPrototypeOf(obj).hasOwnProperty(prop)
推荐封装函数
下面这个函数能清晰区分三种情况:
```jsfunction getPropertySource(obj, key) {
if (!(key in obj)) return '不存在';
if (obj.hasOwnProperty(key)) return '自身属性';
if (Object.getPrototypeOf(obj)?.hasOwnProperty(key)) return '直接原型属性';
return '原型链更上层属性';
}
例如:
```jsconst parent = { inherited: 1 };
const child = Object.create(parent);
child.own = 2;
getPropertySource(child, 'own'); // '自身属性'
getPropertySource(child, 'inherited'); // '直接原型属性'
getPropertySource(child, 'toString'); // '原型链更上层属性'
```
注意不可枚举属性的影响
hasOwnProperty() 和 Object.getPrototypeOf(obj).hasOwnProperty() 都能正确识别不可枚举属性(比如通过 Object.defineProperty 设置的 enumerable: false 属性)。而 Object.keys() 或 for...in 会忽略它们,因此不能用于此场景。
为什么不建议用 in 单独判断?
'prop' in obj 返回 true 只说明属性在整条原型链中存在,无法定位层级。例如 toString 在几乎所有对象中都返回 true,但它来自 Object.prototype,通常离实例很远,不属于“直接原型”。











