Sle*_*v7n 3 javascript constructor extends super
我试图弄清楚 super 在 JavaScript 中是如何工作的。我有一个想法,但我不确定它的准确性,所以我需要一些帮助。
class A {
}
class B extends A {
constructor() {
super();
}
}
class C extends B {
constructor() {
super();
}
}
new C
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,“new”运算符创建一个对象并将其链接到构造函数 C 的原型,构造函数 C 的隐藏属性“thisArg”现在指向新创建的对象
+---------------------+
| function object |
+---------------------+
| - code |
+---------------------+
| - outerScope |
+---------------------+
| - thisArg |
+---------------------+
| - [[Prototype]] |
+---------------------+
| + prototype |
+---------------------+
| + length |
+---------------------+
| + name |
+---------------------+
Run Code Online (Sandbox Code Playgroud)
注意:隐藏属性 thisArg 可以在每次函数调用时隐式(使用访问运算符 '.' 和 '[]')、显式(使用 .call、.apply、.bind 方法)或使用 'new' 运算符进行更改
词法环境的“this”引用将指向 thisArg 所指向的任何函数隐藏属性
回到流程。构造函数 C 被执行,然后 super 将新创建的对象传递给 B 构造函数,构造函数 B 的隐藏属性 thisArg 现在指向新创建的对象
构造函数 B 也会发生同样的情况,它被执行,并且 super 将新创建的对象传递给构造开始的构造函数 A
当 A 完成构造后,它将对象传递给 B
然后B向该结构添加更多槽并向下传递给C
最后C结束构造并返回构造的对象
那么基本上,新创建的对象首先从构造函数冒泡到构造函数,然后向下滴落?
这不是它的工作原理class。它的构造部分与旧的设置接近正确function,但class在这方面的工作方式略有不同。
当您这样做时,在调用构造函数new C之前不会创建该对象。A发生的情况如下:
new调用C的[[Construct]]内部方法并将new.target其设置为C。
C运行之前的任何代码super()。this此时无法访问。C的代码调用 的B[[Construct]] (via super()),但new.target仍设置为C。
B运行之前的任何代码super()。this仍然处于可访问状态。B调用A的 [[Construct]] (通过super()),new.target仍设置为C。
A是基本构造函数,A因此 的 [[Construct]] 创建对象,并根据( )prototype的属性设置其原型。new.targetCA都会运行,并且可以访问this.Bafter中的任何代码super()都会运行(并且可以访问this)。Cafter中的任何代码super()都会运行(并且可以访问this)。A是表达式的结果new。(为了清楚起见,我跳过了上面的一些小细节。)
这就是class构造如何确保新对象按照从基本构造函数 ( A) 到第一个派生构造函数 ( B) 和最后的目标new( C) 的顺序进行初始化。这样,A首先可以访问新对象,然后是B,最后是C。
更多内容请参见上面的规范链接。