Reflect.has() 是 ES6 引入的用于检测对象(含原型链)是否拥有某属性的方法,语义等价于 in 操作符,但更规范、可被 Proxy 的 has 拦截器捕获,且对非对象参数抛 TypeError。

Reflect.has() 是 ES6 引入的标准化方法,用于检测对象(含原型链)是否拥有某个属性,语义上等价于 in 操作符,但更符合“元编程”规范,且在 Proxy 场景中是唯一可拦截的方式。
语法与基本行为一致
Reflect.has(target, propertyKey) 接收两个参数:目标对象和属性名(字符串或 Symbol),返回布尔值。它会沿原型链查找,只要属性在对象自身或任意原型上存在(包括不可枚举属性),就返回 true。
- 与
'prop' in obj行为完全相同,例如:Reflect.has({a: 1}, 'a')→true,Reflect.has({}, 'toString')→true(继承自Object.prototype) - 不区分自有属性和继承属性,也不关心属性是否可枚举或是否为访问器——只要存在即返回
true - 若
target非对象(如null或原始值),直接抛出TypeError,这点比in更严格(in对非对象会强制转为对象,可能产生意外结果)
更适合 Proxy 和元编程场景
当使用 Proxy 时,Reflect.has() 是唯一能触发 has 拦截器的方法;而 in 操作符无法被统一拦截(某些引擎下可能绕过代理)。
- 正确写法:
const p = new Proxy(obj, { has: () => console.log('checked') }); 'x' in p—— 可能不触发;但Reflect.has(p, 'x')一定触发has钩子 - 在封装通用属性检查工具、实现响应式系统或调试代理行为时,优先用
Reflect.has可保证行为可控、可预测
实际迁移建议
将现有 in 表达式替换为 Reflect.has() 通常只需改写语法,但需注意两点:
- 确保
target是对象:可加类型检查,例如obj != null && typeof obj === 'object' && Reflect.has(obj, key) - 避免在热路径中频繁调用(性能差异极小,但
in是语法操作符,略快于函数调用;一般业务代码无需优化此处) - 团队协作中,统一使用
Reflect.has()能提升代码一致性,尤其在涉及 Proxy 或需要显式元操作的模块中
不适用的常见误区
Reflect.has() 不替代 Object.prototype.hasOwnProperty() 或 Object.hasOwn() —— 它始终查原型链,无法判断是否为自有属性。
- 要检测“是否自身拥有”,仍用
Object.hasOwn(obj, key)(推荐,ES2022 新增)或obj.hasOwnProperty(key)(注意防篡改) -
Reflect.has()也不能检测属性是否可读/可写,它只回答“是否存在”这一问题

















