在调用 `super(...)` 之前前向关闭 `this`(或者:"the mind-bending story of WTF seriously")

Forward-closure of `this` before calling `super(...)` (or: "the mind-bending story of WTF seriously")

经过一些摆弄,我最终用 TypeScript 写了这个:

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

而且有效...

暂时搁置为什么我这样做(与我的问题无关)

我的问题是:

我遗漏了一些东西 :/

是的,我想我明白为什么这会困扰你。 GitHub 中的相关问题是 Microsoft/TypeScript#3311。让我们看看我能否回答这些问题:


  • How in the world does it compile when I do things before the call to super ?!

显然是因为 you don't have member initializers。来自链接问题:

You can call super whenever you want if you don't have member initializers...

If you look at how class member initializers are emitted, the reasoning for this becomes fairly clear. Member initializers are emitted after the super call (otherwise your derived-class initializers wouldn't properly overwrite base class initializations); by enforcing the super call to be the first thing the compiler can guarantee that there's exactly one (correct) place to emit those initializers.

You move the super call to any position by removing member initializers -- this makes explicit what you expect the initialization order of each class member to be.

我认为语言设计者认为在 super 调用之前可以做一些合法的事情(例如,进行一些计算以确定要传递给 super 的调用的内容),但是有几件事是有问题的:成员初始值设定项(它作为对 this 的引用发送给 JS),以及对 this 的显式引用。


  • at least this should not be available or I'd rather have done const c = new C(this.method); but it did not compile, complaining that this is not, yet, available

是的,你不能在调用super之前引用裸this.method,因为那时this不一定存在。


  • How can the line const c = new C(() => this.method()); closure this when it is not yet defined ?

我对闭包被接受的猜测是,对 this 的引用不能被视为来自 lexically before super 调用。这可能是也可能不是编译器中的错误或设计限制。在你的情况下,如果 C 的构造函数实际上没有调用函数,那么可能没有问题......闭包可能会推迟 this.method 的取消引用,直到子类构造函数完成之后.但是由于 C 的构造函数可能 调用函数,代码可能不安全。

如果您强烈认为这应该给出编译器警告,您可能想在 GitHub 中提出问题并参考 Microsoft/TypeScript#3311(您无法评论该问题,因为它已被锁定).

希望对您有所帮助。祝你好运!