Reputation: 371
I'm trying to figure out how super really works in JavaScript. I have an idea but I'm not sure of it's exactitude so I need some help.
class A {
}
class B extends A {
constructor() {
super();
}
}
class C extends B {
constructor() {
super();
}
}
new C
In the above code the 'new' operator creates an object and links it to the constructor C's prototype, constructor C's hidden property 'thisArg' now points to the newly created object
+---------------------+
| function object |
+---------------------+
| - code |
+---------------------+
| - outerScope |
+---------------------+
| - thisArg |
+---------------------+
| - [[Prototype]] |
+---------------------+
| + prototype |
+---------------------+
| + length |
+---------------------+
| + name |
+---------------------+
N.B. The hidden property thisArg can be altered at each function call, implicitly (with access operators '.' and '[]'), explicitly (with .call, .apply, .bind methods) or with the 'new' operator
Lexical environment's 'this' reference will then point to whatever functions hidden property thisArg is pointing at
Back to the process. The constructor C gets executed then the super passes up the newly created object to the B constructor, constructor B's hidden property thisArg now points to the newly created object
same happens with the constructor B, it gets executed and the super passes up the newly created object to the A constructor where the construction starts
When A finishes the construction it passes the object down to B
Then B adds more slots to the structure and passes down to C
Finally C ends the construction and returns the constructed object
So basically, the newly created object first bubbles up from constructor to constructor and then trickles down?
Upvotes: 3
Views: 194
Reputation: 1074138
That's not how it works with class
. The construction parts of it would be close to correct with the old function
-based setup, but class
works slightly differently in this regard.
When you do new C
, the object isn't created until the A
constructor is called. Here's what happens:
new
calls C
's [[Construct]] internal method with new.target
set to C
.
C
prior to super()
runs. this
is inaccessible at this point.C
's code calls B
's [[Construct]] (via super()
) with new.target
still set to C
.
B
prior to super()
runs. this
is still in accessible.B
calls A
's [[Construct]] (via super()
) with new.target
still set to C
.
A
is the base constructor, A
's [[Construct]] creates the object, setting its prototype from the prototype
property of new.target
(which is C
).A
constructor runs, and has access to this
.B
after super()
runs (and has access to this
).C
after super()
runs (and has access to this
).A
is the result of the new
expression.(I'm skipping over some minor details above for clarity.)
This is how the class
construct ensures that the new object is initialized in order from the base constructor (A
) to the first derived constructor (B
) and the finally the new
target (C
). That way, A
has access to the new object first, followed by B
, followed by C
.
More in in the specification link above.
Upvotes: 6