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

我正在做一个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?

您使用访问器和“静态”关键字来创build“公共静态字段”:

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

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

ClassElement [Yield]:
MethodDefinition [?产量]
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:静态MethodDefinition
返回true。

所以PropertyMethodDefinition被称为“F”(构造函数,函数对象)作为参数,从而在该对象上创build一个访问器方法 。

至lessIETP(技术预览版),以及6to5和Traceur编译器已经可以工作了。

丹尼尔·艾伦伯格(Daniel Ehrenberg)和杰夫·莫里森(Jeff Morrison)有一个阶段3的ECMAScript提案叫做“类字段” ( Class Fields) ,旨在解决这个问题。

 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; 

Babel通过@ babel / plugin-proposal-class-properties (包含在stage-3预置中 ) 支持转译类字段,所以即使JavaScript运行时不支持,也可以使用此function。


与@ kangax的声明一个getter的解决scheme相比,这个解决scheme也可以是更高性能的,因为这里的属性是直接访问的,而不是通过调用一个函数。

如果这个build议被接受,那么就可以用一种更类似于传统的面向对象的语言(如Java和C ++)来编写JavaScript代码。


编辑 :一个统一的class级领域build议现在在阶段3; 更新到Babel v7.x包。

在ECMAScript 6(截至2015年2月)的最新草案中,所有的类属性都必须是方法,而不是值(ECMAScript中的注释“属性”在概念上与OOP字段相似,除了字段值必须是Function对象,任何其他值,如NumberObject )。

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

  class Agent { } Agent.CIRCLE = 1; Agent.SQUARE = 2; ... 

为了充分利用静态variables我遵循这种方法。 更具体地说,我们可以使用它来使用私有variables或者只有公有的getter,或者同时拥有getter或者setter。 在最后一种情况下,它与上述解决scheme中的一种相同。

 var Url = (() => { let _staticMember = []; return class { static getQueries(hash = document.location.hash) { return hash; } static get staticMember(){ return _staticMember; } }; })(); Usages: console.log(Url.staticMember); // []; Url.staticMember.push('it works'); console.log(Url.staticMember); // ['it works']; 

我可以创build另一个类扩展Url,它的工作。

我用babel将我的ES6代码转换为ES5

@ kangax的答案并不是模仿传统的OOP语言的整个静态行为,因为你不能像const agent = new Agent; agent.CIRCLE; // Undefined那样通过它的实例访问静态属性const agent = new Agent; agent.CIRCLE; // Undefined const agent = new Agent; agent.CIRCLE; // Undefined

如果你想像OOP一样访问静态属性,这里是我的解决scheme:

 class NewApp { get MULTIPLE_VERSIONS_SUPPORTED() { return this.constructor.MULTIPLE_VERSIONS_SUPPORTED; // Late binding for inheritance } } NewApp.MULTIPLE_VERSIONS_SUPPORTED = true; 

testing代码如下。

 class NewApp { get MULTIPLE_VERSIONS_SUPPORTED() { console.log('this.constructor.name:', this.constructor.name); // late binding return this.constructor.MULTIPLE_VERSIONS_SUPPORTED; } } // Static property can be accessed by class NewApp.MULTIPLE_VERSIONS_SUPPORTED = true; const newApp = new NewApp; // Static property can be accessed by it's instances console.log('newApp.MULTIPLE_VERSIONS_SUPPORTED:', newApp.MULTIPLE_VERSIONS_SUPPORTED); // true // Inheritance class StandardApp extends NewApp {} // Static property can be inherited console.log('StandardApp.MULTIPLE_VERSIONS_SUPPORTED:', StandardApp.MULTIPLE_VERSIONS_SUPPORTED); // true // Static property can be overwritten StandardApp.MULTIPLE_VERSIONS_SUPPORTED = false; const std = new StandardApp; console.log('std.MULTIPLE_VERSIONS_SUPPORTED:', std.MULTIPLE_VERSIONS_SUPPORTED); // false