Reflect.has 无法区分自有属性与继承属性,行为与 in 操作符完全一致;要检测自有属性,必须使用 Object.hasOwn 或 Object.prototype.hasOwnProperty.call。

Reflect.has 不能“完美解决”原型链遮蔽导致的判断失真问题,它和 in 操作符行为完全一致 —— 都会沿原型链查找属性,**无法区分自有属性与继承属性**。所谓“替代并完美解决”,是一个常见误解。
Reflect.has 和 in 的行为完全相同
两者都执行“属性存在性检查(property existence check)”,语义是:
“该属性名是否在对象及其原型链上可被访问(即 in [[OwnPropertyKeys]] 或 [[GetOwnProperty]] + 原型遍历)?”
例如:
const parent = { foo: 1 };
const child = Object.create(parent);
child.bar = 2;
'foo' in child; // true(从 parent 继承)
Reflect.has(child, 'foo'); // true(完全等价)
'bar' in child; // true(自有)
Reflect.has(child, 'bar'); // true
它们都无法回答:“foo 是 child 自己定义的,还是从原型来的?”
macOS 微信消息自动化工具。通过 GUI 自动化实现:发送消息给指定联系人、读取聊天内容、监控新消息。适用于需要自动化微信操作的场景,如定时发送、批量回复、消息备份等。依赖 peekaboo 进行屏幕截图和 UI 交互。仅支持 macOS。开源地址:https://github.com/chairmanmia...
真正能区分“自有”与“继承”的方法只有 Object.prototype.hasOwnProperty
若目标是排除原型链干扰、只检测对象自身是否声明了某属性,必须用:
-
obj.hasOwnProperty(prop)(注意:可能被覆盖,需用Object.prototype.hasOwnProperty.call(obj, prop)更安全) -
Object.hasOwn(obj, prop)(ES2022 新增,推荐,专为此场景设计,不可被覆盖)
继续上面的例子:
child.hasOwnProperty('foo'); // false(foo 不是 child 自有)
Object.hasOwn(child, 'foo'); // false
child.hasOwnProperty('bar'); // true
Object.hasOwn(child, 'bar'); // true
为什么有人误以为 Reflect.has 能“解决遮蔽问题”?
混淆常源于两个事实:
-
Reflect.has是函数调用形式,支持动态属性名且不会触发 getter(in会触发),但这和“是否查原型”无关 - 当对象被冻结或禁止扩展时,
Reflect.has和in行为依然一致,都不关心属性是否可枚举、是否为 getter、是否被遮蔽——它们只关心“是否存在”
“遮蔽(shadowing)”本身不是问题:子对象定义同名属性自然会遮蔽父属性,这是 JS 正常机制。判断失真 的根源,其实是开发者混淆了“是否存在”和“是否自有”这两个不同语义。
选哪个?看你要回答什么问题
✅ 想知道“这个 key 在 obj 或其任意原型上能否被 in 检测到?” → 用 in 或 Reflect.has(二者任选,后者适合动态场景)
✅ 想知道“这个 key 是 obj 自己定义的(非继承)?” → 必须用 Object.hasOwn(obj, key)

















