ES6类变量替代

当前在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;
    }
}

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

我知道我可以this.myVar = trueconstructor...但我不想“垃圾”我的构造,特别是当我有一个更大的类20-30 +参数。

我在考虑解决该问题的多种方法,但尚未找到任何好的方法。(例如:创建一个ClassConfig处理程序,并传递一个parameter与类分开声明对象。然后该处理程序将附加到该类。我正在考虑WeakMaps通过某种方式进行集成。)

您将如何处理这种情况?

神乐Pro2020/03/12 20:29:44

我解决此问题的方法是另一种选择(如果您有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可以对属性执行代码完成。一次命中分配所有变量很不错,但是无法编写完整的属性imo不值得(几乎肯定是很小的)性能好处。

GilGreen2020/03/12 20:29:44

好了,您可以在构造函数中声明变量。

class Foo {
    constructor() {
        var name = "foo"
        this.method = function() {
            return name
        }
    }
}

var foo = new Foo()

foo.method()
Gil乐2020/03/12 20:29:44

这是一点静态的静态组合,可以为我工作

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)...
L前端2020/03/12 20:29:44

ES7 类成员语法:

ES7有一个“垃圾”您的构造函数的解决方案。这是一个例子:

class Car {
  
  wheels = 4;
  weight = 100;

}

const car = new Car();
console.log(car.wheels, car.weight);

上面的示例将在中显示以下内容ES6

class Car {

  constructor() {
    this.wheels = 4;
    this.weight = 100;
  }

}

const car = new Car();
console.log(car.wheels, car.weight);

请注意,使用此方法时,并非所有浏览器都支持此语法,并且可能必须将其编译为JS的早期版本。

奖励:对象工厂:

function generateCar(wheels, weight) {

  class Car {

    constructor() {}

    wheels = wheels;
    weight = weight;

  }

  return new Car();

}


const car1 = generateCar(4, 50);
const car2 = generateCar(6, 100);

console.log(car1.wheels, car1.weight);
console.log(car2.wheels, car2.weight);

小卤蛋村村2020/03/12 20:29:44

那老式的方式呢?

class MyClass {
     constructor(count){ 
          this.countVar = 1 + count;
     }
}
MyClass.prototype.foo = "foo";
MyClass.prototype.countVar = 0;

// ... 

var o1 = new MyClass(2); o2 = new MyClass(3);
o1.foo = "newFoo";

console.log( o1.foo,o2.foo);
console.log( o1.countVar,o2.countVar);

在构造函数中,您仅提及那些必须计算的变量。我喜欢此功能的原型继承-它可以帮助节省大量内存(以防万一有很多从未分配的var)。

凯斯丁2020/03/12 20:29:43

2018更新:

现在有第3阶段的提案-我期待在几个月后使这个答案过时。

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

varName = value

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

更新:Chrome 74现在附带此语法。


ES Wiki中针对ES6中提案的注释(最大类别)注释:

没有(有意地)没有直接的声明方式来定义原型数据属性(方法以外的类)或实例属性

类属性和原型数据属性需要在声明之外创建。

在类定义中指定的属性被分配相同的属性,就像它们出现在对象文字中一样。

这意味着您的要求已被考虑,并明确决定反对。

但为什么?

好问题。TC39的好人希望类声明声明和定义类的功能。不是它的成员。ES6类声明为其用户定义其合同。

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

constructor(){
    this.foo = bar
}

在像您建议的构造函数中。另请参见共识摘要

ES7及更高版本

对正在工作了ES7一项新的提案,通过类的声明和表达式可以更简洁的实例变量- https://esdiscuss.org/topic/es7-property-initializers