Alias Accessors S1
中文标题:别名访问器
- 阶段: Stage 1
- 状态: 进行中
- ECMAScript 版本: —
- 同步时间: 2026年8月26日
- English original · 官方仓库
该提案引入了“别名访问器”语法,以减少将类属性转发到另一属性链时的样板代码,解决了访问器通常是累加性而非任意逻辑这一常见情况。它建议使用 alias foo to #foo.value 这样的语法作为显式 getter/setter 对的语法糖,并探讨了聚合、只读别名以及与分组和自动访问器集成的变体。
以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。
别名访问器
状态
阶段:1 (截至 2026 年 1 月全体会议)
作者/提案人:Lea Verou (@leaverou)
历史记录请参见原始提案。
目录
动机
绝大多数(可能超过 90%,但很难证明)访问器用例是累加性的。 它们的概念模型并非完全是任意的逻辑, 而是对常规属性(公有或私有)之上的一层叠加的转换、副作用和访问控制。
在某些情况下,该属性是内部实现细节,且从不被单独访问。 这些情况可以通过自动访问器以及内置装饰器很好地处理。
然而,当使用预先存在的属性(通常是深层嵌套的)作为后备存储时,作者需要退回到通常的样板代码。
本提案探索对于这些用例具有更高信噪比的潜在语法,例如:
其中一些(非互斥的)高层用例包括:
- 封装:隐藏数据源,以便将来可以更改
- 人体工程学:缩短频繁访问的属性链
- 组合:选择性地暴露其他对象或一级协议的 API 表面
- 访问控制:带有公共 getter 的私有属性
轶事证据:
我查看我的访问器用法,它们是(数字未经测量):
- 75% “属性转发”
- 15% 惰性初始计算
- 10% 验证
- 5% 其他
— Nicolò Ribaudo (@nicolo-ribaudo)
为什么不用装饰器?
私有字段作为目标是一个非常重要的用例,目前无法将它们与定义它们的对象分开传递。
但即使是公有字段,装饰器也相当尴尬:
也许通过类似引用声明这样的机制可能会变得可以接受:
或
但这仍然远非理想。
设计
就像自动访问器一样,如果不需要副作用或逻辑,代理另一属性应只涉及属性名称和对保存底层值的属性(链)的引用的少量额外语法。 它甚至可能是一种单独的值支持的访问器类型,接受属性引用而不是初始值,例如:
这将是以下代码的语法糖:
因此,需要讨论的语法是:
- 前置定义的关键字。想法:
aliasdelegateforwardderivedbind可能与bind方法混淆proxy:可能与Proxy构造函数混淆
- 属性名称与被代理属性链之间的分隔符。想法:
=:可能与赋值运算符混淆=>:可能与箭头函数运算符混淆,但也表示绑定viafromthroughto
为具体起见,本文档其余部分将使用 alias/to。
这些属性链基本上是链的 [ . LiteralPropertyName ] | ComputedPropertyName ]。
开头的 this. 是隐含的。
然而,它们不是 Reference:概念上,整个链在每次访问时都会被重新求值。
聚合
有许多情况需要多个属性通过另一个对象转发。
例如,在使用委托/转发模式(如 ElementInternals)时,需要暴露多个属性。
或实现一级协议时:
虽然 alias 已经大大改进,但仍然有点重复。
在第二种情况下没有太多可做的,但当名称相同时,也许可以有一个受解构启发的快捷方式:
只读别名
虽然默认情况下会添加 setter 和 getter,但可以使用可组合 setter 使其只读,可以静默拒绝(DOM 风格)或大声拒绝(JS 风格):
但请注意,只有被代理的属性是只读的才需要这样,否则错误会自然传播:
在此情况下,设置 myElement.form 无论如何都会产生错误,因为 ElementInternals.prototype.form 是只读的。
因此,除非我们希望吞掉写入,否则无需显式阻止写入。
与分组和自动访问器的集成
该提案的另一个方向可能是成为分组和自动访问器的语法扩展。 自定义后备存储已在#14中被请求。
该问题中提出的语法是 accessor(#x) x = 1;。
像 accessor x : #x = 1 这样的语法很可能与 TS 冲突。