Закрытие «this» перед вызовом `super (...)` (или: «всерьез и изумительно рассказывающая о WTF») - PullRequest
0 голосов
/ 29 июня 2018

после некоторой путаницы я закончил тем, что написал это на TypeScript:

 class B extends A{
     constructor() {
         const c = new C(() => this.method());
         super(c);
         c.someMethod(this);
     }
 }

И это работает ...

Давайте оставим в стороне, почему я сделал это на секунду (не имеет отношения к моему вопросу)

Мои вопросы:

  • Как в мире это компилируется, когда я что-то делаю перед вызовом super?!
  • Как может строка const c = new C(() => this.method()); замыкать this, когда она еще не определена?
    • по крайней мере this не должен быть доступен, или я бы предпочел const c = new C(this.method);, но он не компилировался, жалуясь на this is not, yet, available.

Я что-то там упускаю: /

1 Ответ

0 голосов
/ 29 июня 2018

Да, я думаю, я понимаю, почему это беспокоит вас. Соответствующая проблема в GitHub: Microsoft / TypeScript # 3311 . Посмотрим, смогу ли я ответить на эти вопросы:


  • Как в мире это компилируется, когда я что-то делаю перед вызовом super?!

Очевидно, это потому, что у вас нет инициализаторов . Из связанного вопроса:

Вы можете позвонить super, когда захотите, если у вас нет инициализаторов ... ... 1019 *

Если вы посмотрите, как инициализируются члены класса, причины этого становятся достаточно ясными. Инициализаторы членов испускаются после супер-вызова (иначе ваши инициализаторы производного класса не будут правильно перезаписывать инициализации базового класса); принудительно делая супер вызов первым, компилятор может гарантировать, что есть только одно (правильное) место для генерации этих инициализаторов.

Вы перемещаете супер-вызов в любую позицию, удаляя инициализаторы членов - это делает явным то, что вы ожидаете, что порядок инициализации каждого члена класса будет.

Я думаю, что разработчики языка думают, что есть некоторые законные вещи, которые кто-то может сделать до вызова super (например, выполнить некоторые вычисления, чтобы определить, что передать в вызов super), но некоторые вещи проблематичны : инициализаторы членов (которые передают в JS как ссылки на this) и явные ссылки на this.


  • по крайней мере это не должно быть доступно, или я бы предпочел сделать const c = new C(this.method);, но оно не скомпилировалось, жалуясь, что this is not, yet, available

Правильно, вы не можете обратиться к голому this.method до вызова super, потому что this не гарантированно существует в это время.


  • Как может строка const c = new C(() => this.method()); замыкать this, когда она еще не определена?

Мое предположение о том, что закрытие принято, заключается в том, что ссылка на this не должна считаться лексической до вызова super. Это может быть или не быть ошибкой или ограничением дизайна в компиляторе. В вашем случае, если конструктор C на самом деле не вызывает функцию, то, вероятно, нет проблемы ... замыкание может потенциально отложить разыменование this.method до завершения конструктора подкласса. Но поскольку конструктор C может вызвать функцию, код может быть небезопасным.

Если вы твердо уверены, что это должно выдать предупреждение компилятора, вы можете поднять проблему в GitHub и обратиться к Microsoft / TypeScript # 3311 (вы не можете комментировать эту проблему, потому что она заблокирована ).

Надеюсь, это поможет. Удачи!

...