我该如何在ES6类中创建一个"public static field"?
我该如何在ES6类中创建一个"public static field"?
我正在创建一个JavaScript类,并希望像Java中那样拥有公共静态字段。这是相关代码:
export default class Agent { CIRCLE: 1, SQUARE: 2, ...
这是我得到的错误:
line 2, col 11, Class properties must be methods. Expected '(' but instead saw ':'.
看起来ES6模块不允许这样做。有没有办法获得所需的行为,还是我必须编写一个getter?
自从ECMAScript 2022之后,您可以像Java和C#等传统面向类的语言那样进行类似于以下的操作:
class MyClass { static myStaticProp = 42; myProp = 42; myProp2 = this.myProp; myBoundFunc = () => { console.log(this.myProp); }; constructor() { console.log(MyClass.myStaticProp); // Prints '42' console.log(this.myProp); // Prints '42' this.myBoundFunc(); // Prints '42' } }
以上等同于:
class MyClass { constructor() { this.myProp = 42; this.myProp2 = this.myProp; this.myBoundFunc = () => { console.log(this.myProp); }; console.log(MyClass.myStaticProp); // Prints '42' console.log(this.myProp); // Prints '42' this.myBoundFunc(); // Prints '42' } } MyClass.myStaticProp = 42;
这些功能是由Daniel Ehrenberg等人在“静态类特性”和“类字段”提案中添加的。Google Chrome(和新Edge)从版本72开始支持这两个提案,相当于Node.js 12+。自Firefox 69以来,支持公共实例字段,自Firefox 75以来,支持静态实例字段。Safari从版本14.1开始同时支持这两个功能。更多信息请参见caniuse.com。
对于尚未支持这些功能的旧浏览器,您可以使用Babel将类字段转换为ES5。这需要启用@babel/plugin-proposal-class-properties插件(从v7.14.0开始默认在@babel/plugin-env中启用)。
与@kangax的解决方案声明getter相比,这个解决方案也可以更高效,因为这里直接访问属性,而不是通过调用函数访问。
编辑:一个统一的类字段提案现在已经进入第3阶段。
编辑(2020年2月):静态类功能已拆分为不同的提案。感谢@GOTO0!
编辑(2021年3月):除Safari外,所有在2020年4月之后发布的主要浏览器现在都支持此功能!
编辑(2021年6月):两个提案都已被ECMAScript语言委员会TC39接受,并且Safari在14.1版本中提供了此功能!
你可以使用accessor和"static"关键字制作"public static field":
class Agent { static get CIRCLE() { return 1; } static get SQUARE() { return 2; } } Agent.CIRCLE; // 1
查看规范,在14.5 — 类定义(Class Definitions)中,你会看到一些与此相关的内容:)
ClassElement[Yield] :
MethodDefinition[?Yield]
static MethodDefinition[?Yield] ;
因此,你可以跟随链接进入14.5.14 — 运行时语义:类定义求值(Runtime Semantics: ClassDefinitionEvaluation)以仔细检查它是否真的像看起来一样。特别是,在第20步:
- 对于从方法中按顺序排列的每个ClassElement m
- 如果m的IsStatic为false,则:
- 使用proto和false作为参数执行方法PropertyDefinitionEvaluation,令status为其结果。
- 否则,
- 使用F和false作为参数执行方法PropertyDefinitionEvaluation,令status为其结果。
- 如果status是异常完成,则
- 将正在运行的执行上下文的词法环境设置为lex。
- 返回status。
IsStatic在14.5.9中定义
ClassElement : static MethodDefinition
返回true。
因此,使用"F"(构造函数,函数对象)作为参数调用PropertyMethodDefinition
,它又在该对象上创建一个访问器方法。
这个在至少IETP(技术预览版),以及6to5和Traceur编译器中已经可以使用了。