Object.hasOwn是ES2022引入的静态方法,用于安全准确判断对象是否自有指定属性;它绕过原型链干扰、不被对象自身hasOwnProperty覆盖、支持Symbol、仅查自身属性,且对非对象参数抛TypeError。

Object.hasOwn 是什么,为什么比 hasOwnProperty 更可靠
Object.hasOwn 是 ES2022 正式引入的静态方法,用于检测对象是否**自有**(own)某个属性,不查找原型链。它本质上是 hasOwnProperty 的安全替代品,核心差异在于:后者是继承自 Object.prototype 的实例方法,而对象可能被篡改——比如 obj.hasOwnProperty = null 或 obj.hasOwnProperty = () => false,此时调用会出错或返回错误结果;Object.hasOwn 是顶层静态方法,完全绕过对象自身的属性和原型干扰。
常见错误现象包括:
- 在第三方数据(如 JSON 解析结果、用户传入对象)上调用
hasOwnProperty报TypeError: obj.hasOwnProperty is not a function - 对象显式覆盖了
hasOwnProperty,导致检测逻辑静默失效 - 使用
{}.hasOwnProperty.call(obj, key)临时兜底,但写法冗长且易漏
怎么用 Object.hasOwn 替换旧写法
直接把原来用 obj.hasOwnProperty(key) 的地方,换成 Object.hasOwn(obj, key) 即可。参数顺序一致,返回值语义完全相同(布尔值),无兼容性陷阱。
实操建议:
- 搜索项目中所有
hasOwnProperty调用,优先替换为Object.hasOwn(尤其在处理不可信输入时) - 如果需兼容 Node.js Object.hasOwn ?? Object.prototype.hasOwnProperty.call 做降级(但注意:不能直接用
obj?.hasOwnProperty,因为仍可能被覆盖) - ESLint 可配
no-prototype-builtins规则自动提示hasOwnProperty使用点
// ✅ 推荐:安全、简洁、语义明确
if (Object.hasOwn(user, 'email')) {
sendWelcomeEmail(user.email);
}
// ❌ 风险:user 可能覆盖了 hasOwnProperty
if (user.hasOwnProperty('email')) {
sendWelcomeEmail(user.email);
}
// ⚠️ 降级写法(仅必要时)
const hasOwn = Object.hasOwn || Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty);
if (hasOwn(user, 'email')) { ... }
Object.hasOwn 和 in 操作符、Object.keys 的区别
in 检查的是**自身 + 原型链上**是否存在该属性,不是自有属性检测;Object.keys() 返回自有可枚举属性数组,但无法单次判断某 key 是否存在,且性能开销大(要遍历并构造新数组)。
典型误用场景:
- 用
'key' in obj判断“对象自己有没有这个字段” → 实际可能来自原型,比如{}上的toString也会返回 true - 用
Object.keys(obj).includes('key')→ 多余创建数组,且忽略不可枚举属性(而Object.hasOwn能正确识别不可枚举自有属性) -
Object.hasOwn对不可枚举属性返回 true(只要它是对象自身的),这点和hasOwnProperty行为一致
哪些情况 Object.hasOwn 仍然不适用
它只解决“属性是否为对象自有”的问题,不处理其他边界:
- 对
null 或 undefined 调用会直接抛 TypeError(和 hasOwnProperty 一样),所以仍需前置校验:obj != null && Object.hasOwn(obj, key)
- 不能检测 Symbol 属性是否为自有 —— 它支持 Symbol key,但前提是该 Symbol 确实作为自有属性被定义过(这点没问题);真正容易错的是误以为它能“发现隐式 Symbol 属性”,比如
Symbol.iterator 是继承来的,Object.hasOwn(arr, Symbol.iterator) 返回 false
- Proxy 对象的行为取决于 trap 实现,
Object.hasOwn 会触发 has trap,而非绕过代理
真正容易被忽略的是:即使用了 Object.hasOwn,也别忘了检查对象本身是否为 null/undefined —— 这个空值判断,比换函数更重要。
null 或 undefined 调用会直接抛 TypeError(和 hasOwnProperty 一样),所以仍需前置校验:obj != null && Object.hasOwn(obj, key)
Symbol.iterator 是继承来的,Object.hasOwn(arr, Symbol.iterator) 返回 falseObject.hasOwn 会触发 has trap,而非绕过代理










