如何制作一个"公共静态字段"在ES6课程?

时间:2015-02-11 02:42:04

标签: javascript ecmascript-6

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

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

这是我得到的错误:

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

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

5 个答案:

答案 0 :(得分:115)

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

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

Agent.CIRCLE; // 1

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

  

ClassElement [Yield]:
  MethodDefinition [?收率]
  静态 MethodDefinition [?Yield];

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

  
      
  1. 对于每个ClassElement m,按顺序排序      
        
    1. 如果 m的IsStatic为假,那么      
          
      1. 让状态为使用参数proto和false对m执行PropertyDefinitionEvaluation的结果。
      2.   
    2.   
    3. 否则,      
          
      1. 让状态为使用参数F和false对m执行PropertyDefinitionEvaluation的结果。
      2.   
    4.   
    5. 如果状态突然完成,那么      
          
      1. 将正在运行的执行上下文的LexicalEnvironment设置为lex。
      2.   
      3. 退货状态。
      4.   
    6.   
  2.   

先前在14.5.9

中定义了IsStatic
  

ClassElement:static MethodDefinition
    返回true。

因此PropertyMethodDefinition以“F”(构造函数,函数对象)作为参数调用,而creates an accessor method on that object依次调用{{1}}。

already works至少在IETP(技术预览版)中,以及6to5和Traceur编译器。

答案 1 :(得分:41)

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'
    }
}

以上相当于:

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 supports通过@babel/plugin-proposal-class-properties(包含在stage-3 preset中)转换类字段,以便即使您的JavaScript运行时没有使用此功能也可以使用此功能支持它。

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

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

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

答案 2 :(得分:27)

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

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

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

答案 3 :(得分:4)

为了充分利用静态变量,我采用了这种方法。更具体地说,我们可以使用它来使用私有变量或只使用公共getter,或同时使用getter或setter。在最后一种情况下,它与上面公布的解决方案相同。

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'];

我可以创建另一个扩展Url的类,但它有效。

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

答案 4 :(得分:1)

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

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

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

NewApp.MULTIPLE_VERSIONS_SUPPORTED = true;

测试代码如下。



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




相关问题