应使用 object.hasown() 判断对象自有属性,因其不查原型链、可处理 null/undefined 且不受 hasownproperty 重写影响;reflect.has() 会沿原型链查找,易误判;旧环境可用 object.prototype.hasownproperty.call() 兜底。

不能用 Reflect.has() 直接安全检查自有属性,因为它会查原型链;要判断对象自身是否定义了某个属性,得用 Object.hasOwn() —— 这是目前最安全、最推荐的方式。
为什么 Reflect.has() 不适合查自有属性
Reflect.has(target, key) 行为等价于 key in target,它会沿着原型链向上查找。比如:
-
Reflect.has({a: 1}, 'toString')返回true(因为继承自Object.prototype) -
Reflect.has({}, 'constructor')也返回true
这在多数业务场景中属于误判——你通常只关心“这个对象自己有没有这个属性”,而不是“它或它的祖先有没有”。
首选方案:Object.hasOwn()(ES2022+)
这是专为解决自有属性检测而设计的静态方法,不依赖实例方法,也不受原型污染影响:
- 语法简洁:
Object.hasOwn(obj, 'prop') - 自动处理
null/undefined:传入非对象时直接返回false,不会报错 - 绕过被重写的
hasOwnProperty:即使对象自己定义了hasOwnProperty: () => false,Object.hasOwn仍能正确工作
示例:
OpenJDK 24 Windows x64 官方参考实现(24+36),适合 Windows 环境进行 Java 开发、编译、运行和版本兼容性验证。
const obj = { x: 1 };
Object.hasOwn(obj, 'x'); // true
Object.hasOwn(obj, 'toString'); // false(不查原型)
Object.hasOwn(null, 'x'); // false(安全兜底)
兼容旧环境的替代写法
若需支持 ES2022 之前的运行时,可用 Object.prototype.hasOwnProperty.call():
- 必须显式绑定到
Object.prototype,避免调用对象自身的重写方法 - 对
null/undefined需提前防护,否则会报错
稳妥写法:
function hasOwn(obj, key) {
return obj != null && Object.prototype.hasOwnProperty.call(obj, key);
}
hasOwn({y: 2}, 'y'); // true
hasOwn(Object.create({z: 3}), 'z'); // false
为什么不推荐用 Reflect.getOwnPropertyDescriptor?
虽然 Reflect.getOwnPropertyDescriptor(obj, key) 返回 undefined 表示属性不存在(含继承属性),但它:
- 开销更大(要构造描述符对象)
- 无法区分“属性存在但值为
undefined”和“属性根本不存在” - 对不可枚举属性仍能返回描述符,但业务上往往只关心“是否存在”,而非“是否可枚举”
所以它适合查属性特性(如是否可写),不适合做存在性判断。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










