Javascript 深度继承和超级构造函数

Javascript deep inheritance and the super constructor

我想弄清楚 super 在 JavaScript 中的真正作用。 我有一个想法,但我不确定它是否准确,所以我需要一些帮助。

class A {

}

class B extends A {
    constructor() {
        super();
    }
}

class C extends B {
    constructor() {
        super();
    }
}

new C

在上面的代码中,'new' 运算符创建了一个对象并将其链接到构造函数 C 的原型,构造函数 C 的隐藏 属性 'thisArg' 现在指向新创建的对象

+---------------------+
|   function object   |
+---------------------+
| - code              |
+---------------------+
| - outerScope        |
+---------------------+
| - thisArg           |
+---------------------+
| - [[Prototype]]     |
+---------------------+
| + prototype         |
+---------------------+
| + length            |
+---------------------+
| + name              |
+---------------------+

N.B。隐藏的 属性 thisArg 可以在每次函数调用时更改,隐式(使用访问运算符“.”和“[]”)、显式(使用 .call、.apply、.bind 方法)或使用 'new'运算符

词法环境的 'this' 引用将指向任何隐藏的函数 属性 thisArg 指向

回到流程。 构造函数 C 被执行,然后 super 将新创建的对象传递给构造函数 B,构造函数 B 的隐藏 属性 thisArg 现在指向新创建的对象

同样的情况发生在构造函数 B 上,它被执行并且 super 将新创建的对象传递给构造开始的 A 构造函数

当 A 完成构造后,它将对象向下传递给 B

然后 B 向结构中添加更多的插槽并向下传递给 C

最后C结束构造,returns构造出对象

所以基本上,新创建的对象首先从一个构造函数冒泡到另一个构造函数,然后滴落下来?

这不是 class 的工作方式。它的构造部分与旧的基于 function 的设置接近正确,但 class 在这方面的工作方式略有不同。

当您执行 new C 时,在调用 A 构造函数之前不会创建对象。这是发生了什么:

  1. new 调用 C[[Construct]] 内部方法并将 new.target 设置为 C
    1. 运行 super() 之前 C 中的任何代码。 this 此时无法访问。
    2. C 的代码调用 B 的 [[Construct]](通过 super()),new.target 仍设置为 C
      1. Bsuper() 之前的任何代码运行。 this 仍然可以访问。
      2. B 调用 A 的 [[Construct]](通过 super()),new.target 仍设置为 C
        1. 由于 A 是基础构造函数,A 的 [[Construct]] 创建对象,从 prototype 属性 的 new.target(即 C)。
        2. A 构造函数中的任何代码都可以运行,并且可以访问 this
      3. Bsuper() 运行后的任何代码(并且可以访问 this)。
    3. super() 运行后 C 中的任何代码(并且可以访问 this)。
  2. A 创建的对象是 new 表达式的结果。

(为了清楚起见,我跳过了上面的一些次要细节。)

这就是 class 构造确保新对象按顺序 从基本构造函数 (A) 到第一个派生构造函数 初始化的方式(B) 最后是 new 目标 (C)。这样,A 首先可以访问新对象,然后是 B,然后是 C

以上规范 link 中有更多内容。