属性 初始值设定项在声明之前未定义

Property initializers not defined until declared

我正在尝试使用 属性 初始化器将箭头函数用作 class 的方法。 但是在声明该方法之前它们是不可访问的。 如果我更改它们的声明顺序,它会起作用。

这是预期的行为还是 babel 转译

class SampleClass1 {
  method2 = this.method1();
  method1() {
    return "works";
  }
}

console.log((new SampleClass1()).method2); // Works

class SampleClass2 {
  method2 = this.method1();
  method1 = () => {
    return "works";
  }
}

console.log((new SampleClass2()).method2); // Error

下面url是一个babel repl实例,我想演示的代码请参考。

https://babeljs.io/repl/#?evaluate=true&presets=es2015%2Creact%2Cstage-0%2Cstage-2&experimental=false&loose=false&spec=false&code=class%20SampleClass1%20%7B%0A%20%20method2%20%3D%20this.method1()%3B%0A%20%20method1()%20%7B%0A%20%20%20%20return%20%22works%22%3B%0A%20%20%7D%0A%7D%0A%0Aconsole.log(%22(new%20SampleClass1()).method2%22)%3B%0Aconsole.log((new%20SampleClass1()).method2)%3B%0A%0Aclass%20SampleClass2%20%7B%0A%20%20method2%20%3D%20this.method1()%3B%0A%20%20method1%20%3D%20()%20%3D%3E%20%7B%0A%20%20%20%20return%20%22works%22%3B%0A%20%20%7D%0A%7D%0A%0Aconsole.log(%22(new%20SampleClass2()).method2%22)%3B%0Aconsole.log((new%20SampleClass2()).method2)%3B

是的,这是预期的行为。请记住,此 ESnext 提案草案中的语法基本上脱糖为

class SampleClass1 {
  constructor() {
    this.method2 = this.method1();
  }
  method1() {
    return "works";
  }
}

class SampleClass2 {
  constructor() {
    this.method2 = this.method1();
    this.method1 = () => {
      return "works";
    }
  }
}

很明显,您可以从构造函数调用原型方法,但不能调用尚未创建的实例属性的方法。

我将尝试以不同的方式解释它,上下文将是 Babel 转译和 ES2016。

赋值创建变量。

SampleClass2method1只是一个变量,恰好有一个函数作为它的值。

class SampleClass2 {
  method2 = this.method1(); // variable
  method1 = () => {  // oops, variable because of assignment.
    return "works";
  }
}

考虑一下,因为构造函数没有构造包含方法的对象,而只构造了两个变量。

现在,由于您稍后定义了 method1,因此 method2 未定义。然后你尝试调用未定义的东西。

这就是错误消息的原因。

如果像这样删除 ()

class SampleClass2 {
  method2 = this.method1; // no longer an error
  method1 = () => {
    return "works";
  }
}

你在实例化 SampleClass2 时不会出错。

为什么第一个案例有效?

class SampleClass1 {
  method2 = this.method1();
  method1() {
    return "works";
  }
}

这基本上是说将名为 method1 的函数放入 SampleClass1 的原型中,并在构建新对象时,将方法的返回值分配给名为 method2 的变量[原文如此] method1.

不要相信原型相关的东西。

在 Babel 中查看以下代码。

console.log(SampleClass1.prototype.method1) // function body
console.log(SampleClass2.prototype.method1) // nothing

如果我遗漏了什么或犯了错误,请告诉我。希望能帮助到你。 :)