Инициализаторы свойств не определены до объявления

Я пытаюсь использовать инициализаторы свойств, чтобы использовать функции стрелок в качестве методов класса. Но они недоступны, пока метод не объявлен. Если я изменю порядок их объявления, это сработает.

Это ожидаемое поведение или это вавилонская транспиляция

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


person Sagi_Avinash_Varma    schedule 03.04.2016    source источник
comment
В вашем втором блоке отсутствует }.   -  person nnnnnn    schedule 03.04.2016
comment
@nnnnnn спасибо, что указали на ошибку в описании вопроса, в моей кодовой базе я прав. Проблема, с которой я сталкиваюсь, является концептуальной   -  person Sagi_Avinash_Varma    schedule 03.04.2016
comment
Я думаю, что это правильное поведение, вы не можете сохранить результат вызова функции до его определения.   -  person Hitmands    schedule 03.04.2016
comment
@Hitmands, но если метод1 является методом класса. это работает нормально.   -  person Sagi_Avinash_Varma    schedule 03.04.2016
comment
@Sagi_Avinash_Varma такой же, как в образце: (function(){var a=test(); function test(){return "ok"} })() vs (function(){var a=test(); var test=function(){return "ok"} })()   -  person zb'    schedule 03.04.2016
comment
@Sagi_Avinash_Varma, что будет правильным поведением, если вы свяжете эти свойства друг с другом?   -  person zb'    schedule 03.04.2016
comment
@Sagi_Avinash_Varma Имейте в виду, что вы работаете с транспиляцией, методы класса присоединяются к прототипу, инициализаторы свойств создаются, когда класс вызывается с помощью оператора new.   -  person Hitmands    schedule 03.04.2016


Ответы (2)


Да, это ожидаемое поведение. Помните, что синтаксис этого черновика предложения ESnext в основном обесценивает сахар до

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

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

И очевидно, что вы можете вызывать методы прототипа из конструктора, но не методы свойств экземпляра, которые вы еще не создали.

person Bergi    schedule 03.04.2016
comment
ES8 выглядит странно. Может быть, просто предложение свойств класса? - person just-boris; 03.04.2016

Я попытаюсь объяснить это по-другому, и контекстом будет транспиляция Babel и ES2016.

Присваивание создает переменные.

В SampleClass2 method1 это просто переменная, которая имеет функцию в качестве значения.

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 возвращаемое значение метода [sic] method1.

Не верьте вещам, связанным с прототипом.

Проверьте следующий код в Babel.

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

Дайте мне знать, если я что-то пропустил или сделал ошибку. Надеюсь, поможет. :)

person Community    schedule 08.04.2016