JavaScript class 属性 内部构造函数与外部构造函数

JavaScript class property inside vs outside constructor

我很难理解在构造函数内部和外部定义 属性 之间的区别。在下面的示例中,两个属性都可以在实例上以相同的方式访问,有什么区别?

class Foo {
  constructor() {
    this.bar = 1;
  }
  baz = 1;
}
const foo = new Foo();
console.log(foo.bar, foo.baz); // 1 1

他们做同样的事情。

在构造函数外定义 属性 是新的 class 字段语法。如果您需要支持旧版浏览器,请使用构造函数方法,或使用 Babel 将代码首先转换为旧版语法。

请注意 class 字段 运行 在构造函数完成之前 - 在 super 调用之后(如果有的话)或者在构造函数的最开始。

class Foo {
  prop = console.log('Class field running');
  constructor() {
    this.prop2 = console.log('Constructor running');
  }
}
const foo = new Foo();

相关:Private fields(也是很新的语法)必须在构造函数外初始化,这样class可以在编译时了解哪些字段是私有的:

class Foo {
  constructor() {
    this.bar = 1;
    // Not OK:
    // this.#foo = 1;
  }
  // OK:
  #baz = 1;
}
const foo = new Foo();

构造函数初始化允许使用 class 实例化中的值,因此每个实例的值可能不同,而 class 范围内定义的属性对所有实例都是全局的。

如果你想用实例中的值初始化一个 属性,你需要在构造函数中进行。通常,如果您希望某个属性对所有实例通用,您可以在构造函数外部定义它,但如果需要,您也可以在内部进行定义。

实际上,在构造函数中定义 this.bar 在 ES6 中被认为是脏代码。您可以像以前一样通过添加 属性 来扩展任何对象。这就是在 ES5 和更低版本中完成的方式。

ES6 主要只是语法糖,这意味着所有 class 定义都可以归结为“本机”JavaScript 代码。在幕后,您对 baz 的定义将完全按照您定义 bar 的方式最终出现在成绩单中。但是,为了可读性,在 ES6 中添加了句法糖,以更 class-like 的方式定义 属性。