Javascript 我怎样做一个“a”字;“公共静态字段”;在ES6班?

Javascript 我怎样做一个“a”字;“公共静态字段”;在ES6班?,javascript,ecmascript-6,class-fields,Javascript,Ecmascript 6,Class Fields,我正在创建一个Javascript类,我希望有一个类似Java的公共静态字段。以下是相关代码: export default class Agent { CIRCLE: 1, SQUARE: 2, ... 这是我得到的错误: line 2, col 11, Class properties must be methods. Expected '(' but instead saw ':'. 看起来ES6模块不允许这样做。是否有办法获得所需的行为,或者我必须编写一个ge

我正在创建一个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 6的当前草稿中(截至2015年2月),所有类属性都必须是方法,而不是值(请注意ECMAScript中的“属性”)在概念上与OOP字段类似,只是字段值必须是
函数
对象,而不是任何其他值,如
数字
对象

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

 class Agent {
 }
 Agent.CIRCLE = 1;
 Agent.SQUARE = 2;
 ...
使用访问器和“static”关键字创建“publicstaticfield”:

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

ClassElement[收益率]:
方法定义[?产量]
静态方法定义[?产量]

因此,从那里您可以遵循运行时语义:ClassDefinitionEvaluation-来仔细检查它是否真的做了看起来像的事情。具体而言,步骤20:

  • 对于每个类元素m,按方法的顺序排列
  • 如果m的IsStatic为false,则
  • 假设status是使用proto和false参数对m执行PropertyDefinitionEvaluation的结果
  • 否则,,
  • 让status作为使用参数F和false对m执行PropertyDefinitionEvaluation的结果。
  • 如果状态为突然完成,则
  • 将正在运行的执行上下文的LexicalEnvironment设置为lex
  • 返回状态
  • IsStatic在前面的中定义

    ClassElement:静态方法定义
    返回true

    因此,
    PropertyMethodDefinition
    用“F”(构造函数,函数对象)作为参数调用,而“F”又反过来是参数


    这至少在IETP(技术预览版)以及6to5和Traceur编译器中实现。

    为了充分利用静态变量,我采用了这种方法。更具体地说,我们可以使用它来使用私有变量,或者只使用公共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

    有一个由郭树瑜和Daniel Ehrenberg提出的第3阶段ECMAScript方案,旨在解决这个问题。除了第3阶段的建议外,您还可以执行以下操作:

    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;
    
    Google Chrome(和new Edge)在年开始支持这两项提案,相当于。Firefox支持自起的公共实例字段和自起的静态实例字段。有关更多信息,请访问

    对于其他尚不支持这些功能的浏览器(特别是Safari),可以使用来对字段进行分类。这需要启用(或者您可以启用整个)


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

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


    编辑:统一类字段建议现在处于第3阶段

    编辑(2020年2月):静态类功能已拆分为不同的方案。谢谢@GOTO0


    编辑(2021年3月):除了Safari之外,2020年4月之后发布的所有主要浏览器现在都支持此功能

    @kangax的答案并没有模仿传统OOP语言的整个静态行为,因为您无法通过它的实例访问静态属性,比如
    const-agent=new-agent;agent.CIRCLE;//未定义

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

    class NewApp {
      get MULTIPLE_VERSIONS_SUPPORTED() {
        return this.constructor.MULTIPLE_VERSIONS_SUPPORTED; // Late binding for inheritance
      }
    }
    
    NewApp.MULTIPLE_VERSIONS_SUPPORTED = true;
    
    测试代码如下

    classnewapp{
    获取多个受支持的\u版本(){
    console.log('this.constructor.name:',this.constructor.name);//后期绑定
    返回this.constructor.MULTIPLE\u VERSIONS\u SUPPORTED;
    }
    }
    //类可以访问静态属性
    NewApp.MULTIPLE_VERSIONS_SUPPORTED=true;
    const newApp=新的newApp;
    //静态属性可以由其实例访问
    console.log('newApp.MULTIPLE_VERSIONS_SUPPORTED:',newApp.MULTIPLE_VERSIONS_SUPPORTED);//真的
    //继承权
    类StandardApp扩展了NewApp{}
    //静态属性可以被继承
    console.log('StandardApp.MULTIPLE_VERSIONS_SUPPORTED:',StandardApp.MULTIPLE_VERSIONS_SUPPORTED);//真的
    //静态属性可以被覆盖
    StandardApp.MULTIPLE_VERSIONS_SUPPORTED=false;
    const std=新标准应用程序;
    
    console.log('std.MULTIPLE_VERSIONS_SUPPORTED:',std.MULTIPLE_VERSIONS_SUPPORTED);//false
    您使用的是哪个ECMAScript 6引擎实现?@Dai注意,ES6
    语法只是传统JS构造函数和原型的语法糖。我认为您应该将这些属性放在原型上,而不是放在构造函数上,以便通过属性引用可以看到它们从实例中。@Pointy我推断OP试图存储常量以供参考(几乎像C#/.NET
    enum
    )。@MattBrowne是的,但要明确的是
    语法也有某些细微的差异。例如,用
    Class.prototype.method=function(){}声明的方法
    是可枚举的(在for in循环中可见),而
    方法是不可枚举的。对于正在查找的其他人,节点中还不支持静态访问器属性。:/至少从Node.js 6.x+开始,这是受支持的。请注意,如果使用flow,则必须在.fl中添加一行
    不安全。启用\u getters\u和\u setters=true
    class NewApp {
      get MULTIPLE_VERSIONS_SUPPORTED() {
        return this.constructor.MULTIPLE_VERSIONS_SUPPORTED; // Late binding for inheritance
      }
    }
    
    NewApp.MULTIPLE_VERSIONS_SUPPORTED = true;