Accessible Object.prototype.hasOwnProperty S4
中文标题:可访问的 Object.prototype.hasOwnProperty
- 阶段: Stage 4
- 状态: 已完成
- ECMAScript 版本: ES2022
- 同步时间: 2026年8月26日
- English original · 官方仓库
该提案引入了 Object.hasOwn(object, property) 方法,以提供更便捷的方式来检查自有属性,避免了 Object.prototype 方法不可用或被覆盖的问题。它简化了常见的写法,如 Object.prototype.hasOwnProperty.call(object, prop)。
以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。
可访问的 Object.prototype.hasOwnProperty()
关于 Object.hasOwn() 方法的提案,使 Object.prototype.hasOwnProperty() 更易于访问。
👋 现在正在收集社区反馈
请参阅 实现 部分,了解 polyfill 和 codemod,以便今天就在您的代码中使用 Object.hasOwn()。
如果您正在使用 Object.hasOwn(),请在 issue #18 中提供反馈(鼓励正面和/或负面反馈)。
状态
此提案目前处于 第 4 阶段
作者:
- @jamiebuilds (Jamie Kyle, Rome)
- Champion: @bnb (Tierney Cyren, Microsoft)
幻灯片:
动机
如今,编写这样的代码非常常见(尤其是在库代码中):
本提案将该代码简化为:
有许多现有的库使这更加方便:
这是常见做法,因为 Object.prototype 上的方法有时可能不可用或被重新定义。
Object.create(null)
Object.create(null) 将创建一个不继承自 Object.prototype 的对象,使得这些方法无法访问。
重新定义 hasOwnProperty
如果您不直接拥有对象上定义的每个属性,您不能 100% 确定调用 .hasOwnProperty() 就是调用内置方法:
ESLint no-prototype-builtins
ESLint 有一个 内置规则 禁止使用像 hasOwnProperty 这样的原型内置方法。
来自 ESLint 关于
no-prototype-builtins的文档:
此规则的不正确代码示例:
此规则的正确代码示例:
MDN hasOwnProperty() 建议
MDN 关于 Object.prototype.hasOwnProperty 的文档包含 建议 不要直接脱离原型链使用它:
JavaScript 不保护属性名 hasOwnProperty;因此,如果对象可能具有此名称的属性,则有必要使用外部的 hasOwnProperty 来获得正确的结果 [...]
提案
本提案添加了一个 Object.hasOwn(object, property) 方法,其行为与调用 hasOwnProperty.call(object, property) 相同
实现
JavaScript 引擎中 Object.hasOwn 的原生实现可用在:
- 浏览器:
- V8(已发布)
- SpiderMonkey(功能标记)
- JavaScriptCore(进行中)
- 其他:
Object.hasOwn() 的 polyfill 可用在:
可用于从类似库迁移到 Object.hasOwn() 的 codemod:
还有一个 eslint 规则用于强制使用 hasOwn 而不是 hasOwnProperty:
问答
为什么不使用 Object.hasOwnProperty(object, property)?
Object.hasOwnProperty(property) 今天已经存在,因为 Object 本身继承自 Object.prototype,所以定义一个具有不同签名的新方法将是一个破坏性更改。
为什么命名为 hasOwn?
参见 Issue #3
为什么不使用 Map 代替对象作为字典?
摘自 https://v8.dev/features/object-fromentries#objects-vs.-maps
JavaScript 也支持 Maps,这通常是比普通对象更合适的数据结构。因此,在您完全控制的代码中,您可能会使用 Maps 而不是对象。但是,作为开发人员,您并不总能选择表示形式。有时您操作的数据来自外部 API 或某个库函数,它给您一个对象而不是一个 Map。
为什么不将此方法放在 Reflect 上?
Reflect 的目的是包含与每个 Proxy 陷阱一一对应的方法。Proxy 上已经有一个捕获 hasOwnProperty 的方法(getOwnPropertyDescriptor),因此添加额外的陷阱没有意义,所以将此方法放在 Reflect 上也没有意义。