Javascript ES6类变量替代方案

Javascript ES6类变量替代方案,javascript,class,ecmascript-6,Javascript,Class,Ecmascript 6,目前在ES5中,我们中的许多人在框架中使用以下模式来创建类和类变量,这很方便: /ES 5 框架类({ 变量:“string”, 变量2:正确, init:function(){ }, 附加项:函数(){ } }); 在ES6中,您可以以本机方式创建类,但没有选择使用类变量: //ES6 类MyClass{ 常量MY_const='string';//2018更新: 现在有一个第三阶段的建议-我期待着在几个月内使这个答案过时 同时,任何使用TypeScript或babel的人都可以使用以下语法

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

/ES 5
框架类({
变量:“string”,
变量2:正确,
init:function(){
},
附加项:函数(){
}
});
在ES6中,您可以以本机方式创建类,但没有选择使用类变量:

//ES6
类MyClass{
常量MY_const='string';//2018更新:

现在有一个第三阶段的建议-我期待着在几个月内使这个答案过时

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

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

更新:Chrome74现在附带了这种语法


ES wiki中有关ES6中提案的注释()注:

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

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

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

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

但是…为什么? 好问题。TC39的好人希望类声明来声明和定义类的功能,而不是它的成员。ES6类声明为它的用户定义它的契约

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

constructor(){
    this.foo = bar
}
如您所建议的,在构造函数中。另请参见

ES7及以上
一个新的ES7方案正在研究中,它允许通过类声明和表达式使用更简洁的实例变量-

旧的方式如何

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);
在构造函数中,您只提到那些必须计算的变量。
我喜欢这个特性的原型继承——它可以帮助节省大量内存(如果有很多从未分配的变量)。

只是为了添加到Benjamin的答案中-类变量是可能的,但您不会使用
原型设置它们

对于真正的类变量,您需要执行以下操作:

class MyClass {}
MyClass.foo = 'bar';
在类方法中,该变量可以作为
this.constructor.foo
(或
MyClass.foo
)访问

这些类属性通常无法从类实例访问。例如,
MyClass.foo
提供
'bar'
new MyClass()。foo
未定义的

如果还希望从实例访问类变量,则必须另外定义一个getter:

class MyClass {
    get foo() {
        return this.constructor.foo;
    }
}

MyClass.foo = 'bar';
我只使用Traceur测试过这个,但我相信它在标准实现中也能起到同样的作用

。即使使用ES6,我们也在使用基于对象或原型的语言,而不是基于类的语言。在任何
函数X(){}
中,指向
X

当操作符在
X
上使用时,将创建一个继承
X.prototype
的新对象。新对象中任何未定义的属性(包括
constructor
)都将从那里查找。我们可以将其视为生成对象和类属性。

这是静态和get works的一个有点黑客风格的组合

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)...
在您的示例中:

class MyClass {
    const MY_CONST = 'string';
    constructor(){
        this.MY_CONST;
    }
}
由于MY_CONST是原始的,我们可以:

class MyClass {
    static get MY_CONST() {
        return 'string';
    }
    get MY_CONST() {
        return this.constructor.MY_CONST;
    }
    constructor() {
        alert(this.MY_CONST === this.constructor.MY_CONST);
    }
}
alert(MyClass.MY_CONST);
new MyClass

// alert: string ; true
但是如果
MY_CONST
是引用类型,如
static get MY_CONST(){return['string'];}
警报输出为string,则为false。在这种情况下,
delete
操作符可以执行以下操作:

class MyClass {
    static get MY_CONST() {
        delete MyClass.MY_CONST;
        return MyClass.MY_CONST = 'string';
    }
    get MY_CONST() {
        return this.constructor.MY_CONST;
    }
    constructor() {
        alert(this.MY_CONST === this.constructor.MY_CONST);
    }
}
alert(MyClass.MY_CONST);
new MyClass

// alert: string ; true
最后,对于类变量not
const

class MyClass {
    static get MY_CONST() {
        delete MyClass.MY_CONST;
        return MyClass.MY_CONST = 'string';
    }
    static set U_YIN_YANG(value) {
      delete MyClass.MY_CONST;
      MyClass.MY_CONST = value;
    }
    get MY_CONST() {
        return this.constructor.MY_CONST;
    }
    set MY_CONST(value) {
        this.constructor.MY_CONST = value;
    }
    constructor() {
        alert(this.MY_CONST === this.constructor.MY_CONST);
    }
}
alert(MyClass.MY_CONST);
new MyClass
// alert: string, true
MyClass.MY_CONST = ['string, 42']
alert(MyClass.MY_CONST);
new MyClass
// alert: string, 42 ; true

正如Benjamin在其回答中所说,TC39明确决定至少在ES2015中不包含此功能。然而,共识似乎是他们将在ES2016中添加此功能

语法尚未确定,但ES2016有一个允许您在类上声明静态属性的框架

多亏了babel的魔力,您今天就可以使用它了。根据启用类属性转换,您就可以开始了。下面是一个语法示例:

varName = value
class-foo{
静态myProp='bar'
someFunction(){
console.log(this.myProp)
}
}

这个提议还处于早期阶段,所以随着时间的推移,要准备好调整语法。

因为你的问题主要是风格上的(不想用一堆声明填充构造函数),所以也可以从风格上解决

在我看来,许多基于类的语言的构造函数都是以类名本身命名的函数。从风格上来说,我们可以使用它来创建一个ES6类,它在风格上仍然有意义,但不会将构造函数中发生的典型动作与我们正在做的所有属性声明进行分组将实际的JS构造函数作为“声明区域”,然后创建一个名为function的类,我们将其视为“其他构造函数内容”区域,在真正的构造函数末尾调用它

"use strict"; class MyClass { // only declare your properties and then call this.ClassName(); from here constructor(){ this.prop1 = 'blah 1'; this.prop2 = 'blah 2'; this.prop3 = 'blah 3'; this.MyClass(); } // all sorts of other "constructor" stuff, no longer jumbled with declarations MyClass() { doWhatever(); } } "use strict"; class MyClass { properties() { this.prop1 = 'blah 1'; this.prop2 = 'blah 2'; this.prop3 = 'blah 3'; } constructor() { this.properties(); doWhatever(); } }
class Foo {
    constructor() {
        var name = "foo"
        this.method = function() {
            return name
        }
    }
}

var foo = new Foo()

foo.method()
请注意,第二个方法可能看起来更干净,但它也有一个固有的问题,即当使用此方法的一个类扩展另一个类时,
properties
会被重写。您必须为
properties
提供更多唯一的名称以避免这种情况。我的第一个方法没有这个问题,因为它的假构造函数是uniqUEL以类命名。

支持ESN中的类变量。下一步,请检查:


我解决这个问题的方法是(如果你有jQuery可用的话)在一个旧的school对象中定义字段,然后用这个对象扩展类
class SavedSearch  {
    constructor() {
        Object.assign(this,{
            id : '',
            type : '',
            title : '',
            createdAt: new Date(),
        });

    }
}
class SavedSearch  {
    constructor() {
        this.id = '';
        this.type = '';
        this.title = '';
        this.createdAt = new Date();
    }
}
// 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);
// will be accessible only from the module itself
const MY_CONST = 'string'; 
class MyClass {

    // optional, if external access is desired
    static get MY_CONST(){return MY_CONST;}

    // access example
    static someMethod(){
        console.log(MY_CONST);
    }
}
class Foo {
    constructor() {
        var name = "foo"
        this.method = function() {
            return name
        }
    }
}

var foo = new Foo()

foo.method()
class foo{
   constructor(){
     //decalre your all variables
     this.MY_CONST = 3.14;
     this.x = 5;
     this.y = 7;
     // or call another method to declare more variables outside from constructor.
     // now create method level object reference and public level property
     this.MySelf = this;
     // you can also use var modifier rather than property but that is not working good
     let self = this.MySelf;
     //code ......... 
   }
   set MySelf(v){
      this.mySelf = v;
   }
   get MySelf(v){
      return this.mySelf;
   }
   myMethod(cd){
      // now use as object reference it in any method of class
      let self = this.MySelf;
      // now use self as object reference in code
   }
}