【问题标题】:Property initializers not defined until declared在声明之前未定义属性初始化器
【发布时间】:2016-04-03 09:21:57
【问题描述】:

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

这是预期的行为还是 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

【问题讨论】:

  • 您的第二个块缺少 }。
  • @nnnnnn 感谢您指出问题描述中的错误,在我的代码库中我做对了。我面临的问题是一个概念问题
  • 我认为这是正确的行为,你不能在定义之前存储函数调用的结果。
  • @Hitmands 但如果 method1 是类方法。它工作正常。
  • @Sagi_Avinash_Varma 它与示例中的相同:(function(){var a=test(); function test(){return "ok"} })() vs (function(){var a=test(); var test=function(){return "ok"} })()

标签: javascript babeljs ecmascript-next


【解决方案1】:

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

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

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

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

【讨论】:

  • ES8 看起来很奇怪。也许只是“类属性提案”?
【解决方案2】:

我将尝试以不同的方式解释它,上下文将是 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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-02
    • 2015-12-23
    • 2013-09-25
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    相关资源
    最近更新 更多