目前在ES5中,我们很多人在框架中使用以下模式来创建类和类变量,这很舒服:

// ES 5
FrameWork.Class({

    variable: 'string',
    variable2: true,

    init: function(){

    },

    addItem: function(){

    }

});

在ES6中,你可以在本地创建类,但是没有选项可以有类变量:

// ES6
class MyClass {
    const MY_CONST = 'string'; // <-- this is not possible in ES6
    constructor(){
        this.MY_CONST;
    }
}

遗憾的是,上述方法不起作用,因为类只能包含方法。

我知道我能做到。myVar = true在构造函数…但我不想'垃圾'我的构造函数,特别是当我有20-30+参数为一个更大的类。

我想了很多方法来处理这个问题,但还没有找到一个好的。(例如:创建一个ClassConfig处理程序,并传递一个参数对象,该对象与类分开声明。然后处理程序将附加到类。我也在考虑以某种方式集成WeakMaps。)

你会有什么样的想法来处理这种情况?


当前回答

2018年更新:

现在有一个第三阶段的提案——我期待着在几个月内让这个答案过时。

与此同时,任何使用TypeScript或babel的人都可以使用以下语法:

varName = value

在类声明/表达式体中,它将定义一个变量。希望在几个月或几周后,我能够发布更新。

更新:Chrome 74现在船与此语法工作。


ES wiki中关于ES6提案的注释(最大最小类)注意到:

(有意地)没有直接的声明性方法来定义原型数据属性(方法除外)类属性或实例属性 类属性和原型数据属性需要在声明之外创建。 在类定义中指定的属性被赋予与出现在对象字面量中相同的属性。

这意味着你的要求已经被考虑过了,并且被明确地否决了。

但是…为什么?

好问题。TC39的好人希望类声明能够声明和定义类的功能。不是它的成员。ES6类声明为用户定义了它的契约。

记住,类定义定义了原型方法——在原型上定义变量通常不是你要做的事情。 当然,你可以使用:

constructor(){
    this.foo = bar
}

在构造函数中。另见共识摘要。

ES7及以上版本

ES7的一个新提议正在研究中,它允许通过类声明和表达式来实现更简洁的实例变量——https://esdiscuss.org/topic/es7-property-initializers

其他回答

这是一个有点黑客的组合静态和得到工作为我

class ConstantThingy{
        static get NO_REENTER__INIT() {
            if(ConstantThingy._NO_REENTER__INIT== null){
                ConstantThingy._NO_REENTER__INIT = new ConstantThingy(false,true);
            }
            return ConstantThingy._NO_REENTER__INIT;
        }
}

在其他地方使用

var conf = ConstantThingy.NO_REENTER__INIT;
if(conf.init)...

你可以模仿es6类的行为…并使用你的类变量:)

看妈妈……没有课!

// Helper
const $constructor = Symbol();
const $extends = (parent, child) =>
  Object.assign(Object.create(parent), child);
const $new = (object, ...args) => {
  let instance = Object.create(object);
  instance[$constructor].call(instance, ...args);
  return instance;
}
const $super = (parent, context, ...args) => {
  parent[$constructor].call(context, ...args)
}
// class
var Foo = {
  classVariable: true,

  // constructor
  [$constructor](who){
    this.me = who;
    this.species = 'fufel';
  },

  // methods
  identify(){
    return 'I am ' + this.me;
  }
}

// class extends Foo
var Bar = $extends(Foo, {

  // constructor
  [$constructor](who){
    $super(Foo, this, who);
    this.subtype = 'barashek';
  },

  // methods
  speak(){
    console.log('Hello, ' + this.identify());
  },
  bark(num){
    console.log('Woof');
  }
});

var a1 = $new(Foo, 'a1');
var b1 = $new(Bar, 'b1');
console.log(a1, b1);
console.log('b1.classVariable', b1.classVariable);

我把它放到了GitHub上

2018年更新:

现在有一个第三阶段的提案——我期待着在几个月内让这个答案过时。

与此同时,任何使用TypeScript或babel的人都可以使用以下语法:

varName = value

在类声明/表达式体中,它将定义一个变量。希望在几个月或几周后,我能够发布更新。

更新:Chrome 74现在船与此语法工作。


ES wiki中关于ES6提案的注释(最大最小类)注意到:

(有意地)没有直接的声明性方法来定义原型数据属性(方法除外)类属性或实例属性 类属性和原型数据属性需要在声明之外创建。 在类定义中指定的属性被赋予与出现在对象字面量中相同的属性。

这意味着你的要求已经被考虑过了,并且被明确地否决了。

但是…为什么?

好问题。TC39的好人希望类声明能够声明和定义类的功能。不是它的成员。ES6类声明为用户定义了它的契约。

记住,类定义定义了原型方法——在原型上定义变量通常不是你要做的事情。 当然,你可以使用:

constructor(){
    this.foo = bar
}

在构造函数中。另见共识摘要。

ES7及以上版本

ES7的一个新提议正在研究中,它允许通过类声明和表达式来实现更简洁的实例变量——https://esdiscuss.org/topic/es7-property-initializers

截至2021年的最新浏览器(不是IE,请参阅MDN浏览器图表)实现了公共类字段,这似乎是你正在寻找的:

MyClass { 静态foo = 3; } console.log (MyClass.foo);

然而,显然不可能使这是一个const:在ES6类中声明静态常量?

静态getter看起来非常接近:

MyClass { 静态获取CONST() { 返回3; } } MyClass。Const = 4;//财产不受影响 console.log (MyClass.CONST);

我解决这个问题的方法,这是另一个选择(如果你有jQuery可用),是在一个老式的对象中定义字段,然后用该对象扩展类。我也不想在构造函数中添加赋值,这似乎是一个整洁的解决方案。

function MyClassFields(){
    this.createdAt = new Date();
}

MyClassFields.prototype = {
    id : '',
    type : '',
    title : '',
    createdAt : null,
};

class MyClass {
    constructor() {
        $.extend(this,new MyClassFields());
    }
};

——根据Bergi的评论更新。

没有JQuery版本:

class SavedSearch  {
    constructor() {
        Object.assign(this,{
            id : '',
            type : '',
            title : '',
            createdAt: new Date(),
        });

    }
}

你仍然会得到“胖”构造函数,但至少它都在一个类中,并在一次命中赋值。

编辑# 2: 我现在已经走了一圈,现在在构造函数中赋值,例如。

class SavedSearch  {
    constructor() {
        this.id = '';
        this.type = '';
        this.title = '';
        this.createdAt = new Date();
    }
}

为什么?真的很简单,使用上面的加上一些JSdoc注释,PHPStorm就能够在属性上执行代码补全。在一次命中分配所有的变量是很好的,但无法编码完成属性,在我看来,不值得(几乎肯定是微乎其微的)性能收益。