Object.hasOwn 是 ES2022 引入的安全判断对象自有属性的方法,比 in 和 hasOwnProperty 更可靠,不受原型污染影响、不触发 getter、语义明确且性能高效。

Object.hasOwn 是 ES2022 引入的原生方法,用于安全判断对象是否**自有属性**(即非继承属性),比 in 操作符和 hasOwnProperty 更可靠,特别适合防御性编程场景。
为什么不用 in 或 obj.hasOwnProperty?
in 操作符会检查原型链上的属性,容易误判;而 obj.hasOwnProperty 在对象自身重写了该方法(比如 { hasOwnProperty: null })或原型链被污染时会失效。Object.hasOwn 是静态方法,不依赖对象自身状态,调用安全:
- 不受原型污染影响:即使 Object.prototype.hasOwnProperty 被篡改,Object.hasOwn 仍正常工作
- 不访问对象属性:避免触发 getter、Proxy trap 或潜在副作用
- 语义明确:只关心“对象自己有没有这个键”,不涉及原型链遍历逻辑
典型防御性读取写法
在读取前先确认属性存在且为自有属性,可避免 undefined 访问、意外继承值或 getter 异常:
const user = { name: 'Alice', role: 'admin' };
// 安全读取 role,跳过继承或未定义情况
if (Object.hasOwn(user, 'role')) {
const role = user.role; // 此时可放心读取
console.log(role);
}
配合可选链(?.)和空值合并(??)进一步增强健壮性:
立即学习“Java免费学习笔记(深入)”;
Object.hasOwn(obj, 'prop') ? obj.prop : defaultValueObject.hasOwn(obj, 'prop') && typeof obj.prop === 'function' ? obj.prop() : null
与 Object.keys / Object.getOwnPropertyNames 的区别
Object.hasOwn 是单次键存在性检查,性能高、语义聚焦;而 Object.keys 返回所有自有可枚举属性数组,Object.getOwnPropertyNames 返回所有自有属性(含不可枚举)。当只需判断某个键是否存在时,不要用 keys().includes(key)——它创建中间数组、遍历开销大,且无法区分可枚举/不可枚举:
- ✅ 推荐:
Object.hasOwn(obj, 'x') - ❌ 不推荐:
Object.keys(obj).includes('x')(低效、漏掉不可枚举属性) - ⚠️ 注意:
Object.hasOwn不检测 Symbol 属性,若需支持 Symbol 键,应配合Object.getOwnPropertySymbols
兼容性与降级方案
现代浏览器和 Node.js ≥16.9 已原生支持。旧环境可用 polyfill:
if (!Object.hasOwn) {
Object.hasOwn = Object.prototype.hasOwnProperty.call.bind(
Object.prototype.hasOwnProperty
);
}
注意:该 polyfill 在极端情况下(如 Object.prototype.hasOwnProperty 为 null)仍可能失败,但已覆盖绝大多数生产场景。真正严苛环境建议搭配 TypeScript 类型守卫或运行时 schema 验证。


















