Freezing prototypes S1
中文标题:冻结原型
- 阶段: Stage 1
- 状态: 进行中
- ECMAScript 版本: —
- 同步时间: 2026年8月26日
- English original · 官方仓库
该提案旨在允许冻结对象的 \[\[Prototype\]\],而不使对象不可扩展,这与当前方法(如 Object.freeze)同时阻止添加新属性不同。其动机来自派生类,其中原型应保持固定,但仍可能添加静态方法,以及像 TextNode 这样的 Web 平台类,可以从冻结原型中受益而不需要成为异质对象。
以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。
冻结原型
当前状态
阶段 1 - 正在探索设计空间的范围。
提案
目前,不可能在不使对象不可扩展(即阻止向对象添加新属性)的情况下冻结对象的 [[Prototype]] 内部槽:Object.preventExtensions、Object.seal 和 Object.freeze 都会将其参数标记为不可扩展。(实际上,规范中用于冻结非异质对象原型的机制是将 [[Extensible]] 内部槽设置为 false。)
ECMA-262 定义了不可变原型异质对象,这些对象的原型不能更改,但仍然可以是可扩展的。ECMAScript 中唯一的此类对象是 Object.prototype,不过 Web 平台的 WindowProxy 异质对象 的行为类似。目前没有方法创建这些对象。
本提案将添加某种方式来冻结对象的 [[Prototype]],而不使对象不可扩展。
参见 tc39/ecma262#538 讨论此问题的 issue。
动机
一个主要的动机场景是派生类。在派生类中调用 super() 将调用该类的 [[Prototype]] 在 super() 调用时指向的内容。但除了少数罕见情况,类的作者通常期望它保持不变,并且可能希望强制执行这一点,而不一定阻止以后向类添加新的静态方法。
像 TextNode 这样的 Web 平台类与 ECMAScript 的 class {} 类不同,它们总是调用其原始的超类构造函数。如果它们能够冻结其 [[Prototype]] 可能更合理,但将它们变成异质对象并不理想——如果语言本身能够解释它们的行为而不需要任何异质性,那就更好了。
细节 / 开放问题
目前尚不清楚此提案的 API 会是什么样子。两种可能的设计(非详尽列表):
- 两个新的 Reflect 方法(以及相应的陷阱),用于设置和查询原型的不可变性
- 如何/能否/应当如何与现有的陷阱保持一致,特别是
isExtensible陷阱?
- 如何/能否/应当如何与现有的陷阱保持一致,特别是
- 一个新的选项包参数传递给
preventExtensions和isExtensible,指定它们只应应用于[[Prototype]]- 更难以进行特性检测;如果你在不支持该选项的实现上传递该选项,你将冻结超出预期的内容