如何在ES6课程中创建"公共静态字段"?

aeb*_*bis 81 javascript ecmascript-6

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

export default class Agent {
    CIRCLE: 1,
    SQUARE: 2,
    ...
Run Code Online (Sandbox Code Playgroud)

这是我得到的错误:

line 2, col 11, Class properties must be methods. Expected '(' but instead saw ':'.
Run Code Online (Sandbox Code Playgroud)

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

kan*_*gax 127

使用访问器和"静态"关键字创建"公共静态字段":

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

Agent.CIRCLE; // 1
Run Code Online (Sandbox Code Playgroud)

看一个规范,14.5 - 类定义 - 你会看到一些可疑的相关内容:)

ClassElement [Yield]:
  MethodDefinition [?Yield]
  static MethodDefinition [?Yield];

所以从那里你可以按照14.5.14 - 运行时语义:ClassDefinitionEvaluation - 来仔细检查它是否真的像它看起来那样.具体来说,第20步:

  1. 对于每个ClassElement m,从方法开始
    1. 如果m的IsStatic是假的,那么
      1. 设状态是使用参数proto和false对m执行PropertyDefinitionEvaluation的结果.
    2. 其他,
      1. 令状态为使用参数F和false对m执行PropertyDefinitionEvaluation的结果.
    3. 如果状态是突然完成,那么
      1. 将正在运行的执行上下文的LexicalEnvironment设置为lex.
      2. 退货状态.

IsStatic在早期定义14.5.9

ClassElement:static MethodDefinition
返回true.

因此PropertyMethodDefinition,使用"F"(构造函数,函数对象)作为参数调用,然后在该对象上创建一个访问器方法.

已经工作至少IETP(技术预览版),以及6to5和Traceur编译器.

  • 至少从 Node.js 6.x+ 开始,这是受支持的。 (2认同)

Tim*_* Gu 48

Daniel Ehrenberg和Jeff Morrison 提出了一个名为"Class Fields"的第3阶段ECMAScript提案,旨在解决这个问题.

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'
    }
}
Run Code Online (Sandbox Code Playgroud)

以上相当于:

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;
Run Code Online (Sandbox Code Playgroud)

Babel 支持通过@ babel/plugin-proposal-class-properties(包含在stage-3预设中)转换类字段,这样即使JavaScript运行时不支持,也可以使用此功能.


与@ kangax声明getter的解决方案相比,此解决方案也可以更高效,因为此处直接访问属性而不是通过调用函数.

如果这个提议被接受,那么就有可能以类似于传统的面向对象语言(如Java和C♯)的方式编写JavaScript代码.


编辑:统一的班级字段提案现在处于第3阶段; 更新到Babel v7.x软件包.

  • 我认为相关提案实际上是[这个](https://github.com/tc39/proposal-static-class-features/)(_静态类特征_)。 (2认同)

Dai*_*Dai 29

在ECMAScript 6的当前草案中(截至2015年2月),所有类属性必须是方法,而不是值(注意ECMAScript中的"属性"在概念上类似于OOP字段,除了字段值必须是Function对象,不是任何其他值,如a NumberObject).

您仍然可以使用传统的ECMAScript构造函数属性说明符指定它们:

 class Agent {
 }
 Agent.CIRCLE = 1;
 Agent.SQUARE = 2;
 ...
Run Code Online (Sandbox Code Playgroud)

  • 请注意,无论如何,ES6"class"语法只是传统JS构造函数和原型的语法糖. (11认同)
  • @MattBrowne是的,但要明确`class`语法也有一些细微差别.例如,使用`Class.prototype.method = function(){};`声明的方法是*enumerable*(使用for-in循环可见),而`class`方法不可枚举. (2认同)