Как заставить работать подъем для расширенных классов?

Я говорю о:

class MyAction {
}
class MyActionEdit extends MyActionNew { // <-- error pointing here
}
class MyActionNew extends MyAction {
}

Я получаю следующую ошибку: Uncaught ReferenceError: Cannot access 'MyActionNew' before initialization.

Я не создаю экземпляр до загрузки всех js. Так что я не понимаю, почему здесь не работает подъем. Проблема в том, что я не могу изменить порядок определений классов (они загружаются из разных файлов и объединяются в один большой скрипт - в этом примере 3 объединенных файла).

Я уже читал этот и многие другие вопросы, но никто не ответил на мой вопрос.

Это здесь работает, например:

class MyAction {
}
let test: MyActionNew = new MyActionNew(); // <- Hoisting works here
class MyActionEdit extends MyAction {
}
class MyActionNew extends MyAction {
}

Как я могу справиться с этим? Я не знаю, поможет ли это, но я использую typescript для создания файлов javascript. Может есть что?

Связано: Класс Typescript: класс будет поднят, когда Я использую два класса?

Я прочитал все вопросы с поднятием тега здесь, в stackoverflow, но не нашел ответа.


person SuperNova    schedule 11.09.2020    source источник
comment
там вверху вы расширяете MyActionNew и вниз вы расширяете MyAction ведь они теперь правильные   -  person Ifaruki    schedule 11.09.2020
comment
Javascript выполняется в два этапа: 1) разбор/компиляция, 2) время выполнения. Подъем работает, потому что определенные вещи, такие как имена переменных, создаются на этапе синтаксического анализа и, следовательно, уже существуют во время выполнения. Но то, что вы хотите, происходит на протяжении всего шага синтаксического анализа, и на этом этапе порядок должен быть логичным; подъёма там нет.   -  person deceze♦    schedule 11.09.2020
comment
короче - why hoisting is not working here - потому что определения классов не поднимаются   -  person Jaromanda X    schedule 11.09.2020
comment
Your second example does not work on the Typescript Playground.   -  person Titulum    schedule 11.09.2020
comment
@Thomas Здесь нет круглого расширения. Это просто MyActionMyActionNewMyActionEdit. Просто порядок объявления перепутан.   -  person deceze♦    schedule 11.09.2020
comment
В соответствующей ссылке приведен пример с классом Hero. Здесь в stackoverflow есть много ответов, которые говорят, что классы подняты и что это поведение изменилось между ES5 и ES6. Взгляните на этот ответ: stackoverflow.com/questions/35537619/   -  person SuperNova    schedule 11.09.2020


Ответы (2)


В соответствующей ссылке приведен пример с классом Hero. Здесь в stackoverflow есть много ответов, которые говорят, что классы подняты и что это поведение изменилось между ES5 и ES6. Взгляните на этот ответ: Почему классы ES6 не поднимаются?

Да, но нет. Правильно, что имя класса поднято. Впрочем, это скорее не имеет отношения к вашей ситуации.

Javascript выполняется в два этапа:

  1. Разбор/компиляция
  2. Время выполнения

На этапе синтаксического анализа механизм Javascript разбирает ваш код на части, читает его, размечает его и, как правило, преобразует в исполняемую форму. На этом этапе он определяет общие структуры, которые он будет использовать во время выполнения, в том числе имена объектов и область их действия. Таким образом, имя MyActionEdit будет создано в правильной области. Вот что такое подъем. Потому что на втором этапе среды выполнения, когда код действительно запускается, это имя уже будет существовать, даже если оно появится позже в области видимости:

console.log(foo);

var foo = 'bar';

Это выполняется так:

  1. Проанализируйте var foo и создайте область с зарезервированным именем.
  2. Время выполнения: выполните console.log(foo), затем выполните foo = 'bar'.

Вот почему это не вызывает ошибку и регистрирует undefined. Вот что такое подъем.

Теперь классы также полностью определяются во время синтаксического анализа. На этапе анализа создаются классы. Если этот шаг синтаксического анализа завершается успешно, то классы уже подняты и доступны во время выполнения.* Но это не имеет значения, поскольку порядок объявлений во время синтаксического анализа неправильный, а Javascript не может extend класс, который еще не был объявлен. Он должен был бы проигнорировать это первое объявление класса, перейти к следующему, а затем повторить процесс синтаксического анализа, чтобы объявить ранее пропущенное объявление. Это может привести к бесконечным циклам и, как правило, крайне неэффективно. Или, если он может сначала поднимать классы, в каком порядке их следует поднимать?! Как движок должен знать, что нужно поднять объявление класса в том порядке, в котором они должны быть, чтобы объявления имели логический смысл?

Вы должны объявить свои классы в правильном порядке.

* За исключением того, что они недоступны до их объявления, потому что такое поведение при подъеме считается запутанным и явно подавляется TDZ.

person deceze♦    schedule 11.09.2020
comment
Хорошо, это, к сожалению, имеет смысл для меня. Поэтому я должен изменить свой сборщик файлов, чтобы управлять правильным порядком объединения файлов. Спасибо за разъяснения. Я уже принял твой ответ. - person SuperNova; 11.09.2020

Классы JavaScript не поднимаются. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes

person Griffin    schedule 11.09.2020
comment
Я это уже читал. Но это кажется верным только для ключевого слова класса. Поскольку я использую машинописный текст, я могу вывести класс в любой другой формат. Но я не понимаю, если есть декларация, где подъем будет работать или нет. Я часами гуглил и читал о переполнении стека, прежде чем опубликовал свой вопрос. - person SuperNova; 11.09.2020