如何在 ES6 类中创建“公共静态字段”?

新手上路,请多包涵

我正在制作一个 Javascript 类,我希望有一个像 Java 中那样的公共静态字段。这是相关代码:

 export default class Agent {
    CIRCLE: 1,
    SQUARE: 2,
    ...

这是我得到的错误:

 line 2, col 11, Class properties must be methods. Expected '(' but instead saw ':'.

看起来 ES6 模块不允许这样做。有没有办法获得所需的行为,还是我必须写一个吸气剂?

原文由 aebabis 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 423
2 个回答

您使用访问器和“静态”关键字制作“公共静态字段”:

 class Agent {
    static get CIRCLE() {
      return 1;
    }
    static get SQUARE() {
      return 2;
    }
}

Agent.CIRCLE; // 1

查看规范 14.5 — 类定义 — 您会看到一些可疑的相关内容 :)

类元素[产量]:

方法定义[?产量]

静态 MethodDefinition[?Yield] ;

因此,您可以从那里转到 14.5.14 — 运行时语义:ClassDefinitionEvaluation — 仔细检查它是否真的像它看起来那样做。具体来说,第20步:

  1. 对于每个 ClassElement m,按方法的顺序
    1. 如果 m 的 IsStatic 为 false ,则
      1. 令状态为使用参数 proto 和 false 对 m 执行 PropertyDefinitionEvaluation 的结果。
    2. 别的,
      1. 令 status 为使用参数 F 和 false 对 m 执行 PropertyDefinitionEvaluation 的结果。
    3. 如果状态是突然完成,则
      1. 将运行的执行上下文的 LexicalEnvironment 设置为 lex。
      2. 返回状态。

IsStatic 是在 14.5.9 之前定义的

类元素:静态方法定义

归真。

所以 PropertyMethodDefinition 以“F”(构造函数,函数对象)作为参数调用,它又 在该对象上创建一个访问器方法

这至少在 IETP(技术预览)以及 6to5 和 Traceur 编译器中 已经有效

原文由 kangax 发布,翻译遵循 CC BY-SA 3.0 许可协议

从 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 等人的 “静态类功能”“类字段” 提案中。谷歌浏览器(和新的 Edge)在 版本 72 开始支持这两个提案,相当于 Node.js 12+ 。 Firefox 从 69 版 开始支持公共实例字段,从 75 版开始支持静态实例字段。 Safari 从 14.1 版 开始支持这两种方式。在 caniuse.com 上查看更多信息。

对于尚不支持这些功能的旧浏览器,您可以使用 Babel转换 类字段。这需要启用 @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 版中提供了此功能!

原文由 Timothy Gu 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题