Class Brand Checks S1
中文标题:类品牌检查
- 阶段: Stage 1
- 状态: 进行中
- ECMAScript 版本: —
- 同步时间: 2026年8月26日
- English original · 官方仓库
该提案为 ECMAScript 类引入了一种 class.hasInstance() 语法形式,提供直接的品牌检查,以测试对象是否具有类品牌,这比私有字段的“鸭子类型”检查更为通用和直观。它解决了 instanceof(基于原型)的局限性,并避免为品牌检查添加不必要的私有字段。
以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。
class.hasInstance()
本提案为 ECMAScript 代码类添加了一种 class.hasInstance() 品牌检查 语法形式。
阶段:1
作者:HE Shi-Jun (@hax), XU Tian-Yang (@XGHeaven), Tu Qiang(@YuriTu)
提案 champion:HE Shi-Jun, XU Tian-Yang, Tu Qiang
实验性实现
- Babel 由 @YuriTu 实现
- TypeScript 由 @Jack-Works 实现
动机
关于品牌检查有着很长的讨论历史,并且在该领域有多种努力。最近的相关提案是“私有字段的品牌检查”。在讨论该提案时,https://github.com/tc39/proposal-private-fields-in-in/issues/13 的作者提出了另一种设计方向。与其采用鸭子类型风格的检查(#field in obj),我们可以提供一种更通用的类品牌检查(class.hasInstance(obj)),即一种“真正的”instanceof 检查。在许多情况下,这更接近程序员的意图,并且与其他基于类的面向对象编程语言的概念模型更相似。
instanceof 默认是基于原型的,因此 C.isC(Object.create(C.prototype)) 将通过测试。请注意,许多程序员仍然使用 instanceof,尤其是那些来自其他面向对象语言的程序员。即使他们知道 instanceof 的局限性,并且存在 Symbol.hasInstance 可用于“定制”instanceof,人们也会忽略它们,因为没有简单的方法来“修复”它。
正如 private-in 提案所述,人们可以利用私有字段和私有 in 语法来执行品牌检查,但这只是对私有字段的过度使用。即使人们实际上不需要私有字段,也需要添加一个私有字段。不幸的是,私有字段与普通数据属性在语义上存在显著差异,因此引入私有字段可能会引入破坏性变更,并可能降低代码与许多库/框架的互操作性。
即使你已经出于正当理由使用私有字段,这也会导致问题:
程序员是否应该更新 isC 的实现?如果你将 #x in o 视为类似鸭子类型检查的事物,你应该添加 && #y in o,但在几乎所有情况下,这段代码是冗余的。但是,在某些边缘情况下(例如 #y 的初始化器抛出,如当前私有字段草案所规定,你会得到一个具有 #x 但没有 #y 的对象),你需要再次考虑。这给编码者和代码审查者带来了困惑和不必要的负担。
根本问题是,在大多数情况下,人们想要的是一个通用的“instanceof”测试,逐个测试字段的存在性并不能真正传达程序员的意图。
一个更好的解决方案:
实际上,它也允许程序员使用 Symbol.hasInstance 来“修复”instanceof,如果他们愿意的话:
演示文稿
类品牌检查与私有字段交互的边缘情况分析
待定
语法和命名问题
class.hasInstance 元语法与 类属性访问表达式 提案冲突,已经有一个 issue 讨论此事。如果我们决定将 class.foo 保留给类属性,我们需要找到其他语法,例如 class::hasInstance。
关于命名,我选择了 .hasInstance,它遵循 Symbol.hasInstance,尽管总会有其他选择:.hasBrand 或 .checkBrand。