【问题标题】:Member variables in ES6 classesES6 类中的成员变量
【发布时间】:2015-04-03 05:15:56
【问题描述】:

有没有办法使用 ECMAScript6 class 表示法来声明静态类变量或实例变量的默认值?如果没有class,我的想法会写成

function MyClass(arg) { if(arg) this.arg = arg; }
MyClass.classVariable = 42;
MyClass.prototype.arg = "no arg specified";

在我看来,最明显的类似 ES6 的符号应该是

class MyClass {
    constructor(arg) { if(arg) this.arg = arg; }
    static let classVariable = 42;
    let arg = "no arg specified";
}

但这不起作用,因为根据the current spec draftClassElement 的唯一产生是静态和实例方法以及分号本身。好的,可以使用一对 getter 和 setter 方法来实现与我概述的语义相似的语义,但我猜这会带来严重的性能损失和非常奇怪的语法。

是否有一些草案建议以一种或另一种方式在class 表示法中包含变量?如果是这样,建议的语法是什么,在哪里发布,在哪里讨论过,讨论如何进行,这方面的当前状况是什么?就目前而言,如果以前在任何层面都没有讨论过这样的事情,这个问题就无法回答,但我认为这不太可能。


一些背景知识:我目前正在使用 Google 闭包编译器执行高级编译,使用 ES6 作为输入。为此,我需要一个地方来放置成员变量的类型注释,并且我曾经使用 /** @type {string} */ MyClass.prototype.arg; 之类的语法来放置它们,这是 ECMAScript 中的语义无操作,但可以很好地为闭包编译器提供类型信息,并且简单。我还没有找到一个类似的好方法来使用class 构造来做到这一点。但是,如果您想解决这方面的问题,那将是一个评论。上面的问题是关于成员声明,​​它不仅仅是无操作,所以这就是这里应该讨论的答案。

【问题讨论】:

  • 我认为class Foo { get foo() { return 123 } } 已经很接近了
  • 我认为@kangax 的技术是任何将充当抽象类的最佳选择。我遇到过同样的问题;这是我写的一个控制器,它可能/可能不会给你一些想法。基类的构造函数为独特的功能(在这种情况下合并数组)完成了所有繁重的工作,因此您只需确保始终在子类构造函数上调用super()github.com/affirmix/tungstenjs/blob/master/src/controller.js。你可以看到子类最终看起来不会太讨厌:github.com/affirmix/tungstenjs-todomvc/blob/master/src/…

标签: javascript class member static-members ecmascript-6


【解决方案1】:

ES6 几乎肯定不会涵盖定义类变量的语法。只能使用类语法定义方法和 getter/setter。这意味着您仍然需要使用 MyClass.classVariable = 42; 路由来获取类变量。

如果你只是想用一些默认值初始化一个类,你可以使用丰富的函数参数和解构默认值的新语法集。举个简单的例子:

class Foo {
    constructor(foo = 123) {
        this.foo = foo;
    }
}

new Foo().foo == 123
new Foo(42).foo == 42

【讨论】:

  • 如果您在其他函数中访问在构造函数中设置的类属性,则此方法实际上不起作用。见*.com/questions/20279484/…
  • @Jacob 在我给出的示例中,我不是在构造函数中设置类属性,而是在默认情况下设置实例属性。但是,如果您想从实例的函数中访问类属性,可以使用 this.constructor.classProperty 访问它。
  • Class body and method definitions原型方法 部分。
【解决方案2】:

我没有使用 Google Closure Compiler,但是使用 Babel,您可以声明 static(范围为 class)变量,如 here 所述。由于static 成员对 React 的实用性,本文重点关注 React,但总体上适用于 ES6 classes。

语法接近您建议的语法:

class MyClass {
    constructor(arg) { if(arg) this.arg = arg; }
    static defaultArg = 42;
    let arg = MyClass.defaultArg;
}

请注意,您必须将 'es7.classProperties' 添加到您的 .babelrc 才能编译。请参阅Babel 5.0.0 release notes 了解更多信息。

我不知道是否有办法将static 声明为const

【讨论】:

    【解决方案3】:

    虽然它不是 ES6 规范的一部分,但它看起来即将推出,并且已经得到 Babel 和其他一些人的支持。

    这是规格: https://github.com/jeffmo/es-class-fields-and-static-properties

    以及所有提案及其状态的完整列表: https://github.com/tc39/ecma262

    【讨论】:

    • “这看起来像是在 ES7 中出现”它肯定没有,功能集已经完成并且仅包含 2 个第 4 阶段提案。
    • @zerkms 你说得对,我修改了我的答案,谢谢指正!我没有意识到 es7 已经完成了。
    • 它看起来确实在节点 12 中,因此您现在可以在没有 Babel 或其他转译器的情况下使用它。