Object.getOwnPropertyDescriptors S4
- 阶段: Stage 4
- 状态: 已完成
- ECMAScript 版本: ES2017
- 同步时间: 2026年8月26日
- English original · 官方仓库
该提案引入了 Object.getOwnPropertyDescriptors,作为现有单数方法的复数对应项,允许在一次调用中检索对象的所有自有属性描述符。它旨在简化常见的模式,如浅拷贝、合并和混入,避免 Object.assign 的陷阱,例如调用 getter 和吞没行为。
以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。
Object.getOwnPropertyDescriptors 提案(Polyfill)
冠军(Champion)
在阶段 0,Rick Waldron 同意支持此提案。 然而,当前 的官方冠军是 Jordan Harband。
状态
此提案可能与 Reflect.getOwnPropertyDescriptors 相同,但为了与其他复数版本保持一致,它被描述为 Object 的公共静态方法。
动机
ECMAScript 中没有单一方法能够简化两个对象之间的正确复制。如今,函数式编程和不可变对象已成为复杂应用的重要组成部分,每个框架或库都在实现自己的样板代码,以便在组合对象或原型之间正确复制属性。
在使用 Object.assign 作为回退方案时,存在很多混乱,且大多数时候会产生不希望的行为,因为它的复制方式会吞没行为:它直接访问属性和符号而不是其描述符,丢弃了可能的访问器,这可能在组合更复杂的对象或类原型时导致危险。
检索所有描述符(无论是否可枚举)也是实现基于 class 及其原型的组合的关键,因为默认情况下,它们具有不可枚举的方法和访问器。
装饰器也可以轻松地一次性从另一个类或混入中获取所有描述符,并通过 Object.defineProperties 分配它们。过滤不需要的描述符也会更简单,且每次需要时减少重复。
最后但同样重要的是,与 Object.assign 相比,两个未知对象之间的浅拷贝将不会出现意外。
常见问题解答
是否应该有 Reflect.getOwnPropertyDescriptors?
由于此提案的主要目标是简化一些常见的样板代码,并与存在单一版本方法但缺少复数版本的事实保持一致,因此进一步保持一致性,也可能需要添加当前 Reflect.getOwnPropertyDescriptor 方法的复数版本。
更新:委员会此前已决定 Reflect 仅用于镜像 Proxy 陷阱,因此这不是一个选项。
提议的解决方案
作为 Object.getOwnPropertyDescriptor 的复数版本,此提案涉及在一次操作中检索通用对象的所有自有描述符。
此提案的 polyfill 可能如下所示:
示例
polyfill 展示了一种替代方案,友好于 ES2015,改进了需要兼容 ES5 或部分 ES2015 引擎的样板代码。
现在 Object.getOwnPropertyDescriptors 已就位,在两个对象之间进行真正浅拷贝或克隆操作所需的一切,如下例所示:
基于对象的可能的混入解决方案也可以从本提案中受益:
假设你想要一个 Object.assign 的版本,它使用 [[DefineOwnProperty]]/[[GetOwnProperty]] 而不是 [[Set]]/[[Get]],以避免副作用并复制 setter/getter,但仍然使用可枚举性作为区分因素。
在提案之前,这样的方法可能如下所示:
然而,如果 Object.getOwnPropertyDescriptors 可用,上述样板代码将如下所示: