Why doesn't the constructor automatically call super()
?
The reason for this is so that you have the flexibility to decide where in the constructor to make the call. You can choose when and how to initialize the parent class. For example:
constructor(foo) {
let bar;
if (foo) {
bar = /*...*/;
} else {
bar = /*...*/;
}
super(bar);
}
This approach is allowed as long as no code before the super
call references this
or super.xyz
.
The language could have been designed to automatically add a call to super
at the beginning of the constructor if it wasn't present at all, similar to Java. However, this decision was intentional.
Does super()
both call the base constructor and set the prototype? It seems incorrect.
No, super()
only calls the base constructor. The prototype is established before your constructor is invoked. This behavior mirrors the way it would be done in older ES5 syntax like this:
function Derived() {
Base.call(this);
}
....where:
function Base() {
}
function Derived() {
Base.call(this);
}
Derived.prototype = Object.create(Base.prototype);
Derived.prototype.constructor = Derived;
Why is super()
necessary even when I don't plan on calling the base constructor?
If you have no intention of calling the base constructor, then perhaps your subclass shouldn't actually be extending the base class. In a statically-typed language, you might consider making the base class an interface instead. In JavaScript, you have more flexibility - you can make your subclass behave like the desired object without having to extend its functionality. If maintaining an instanceof relationship is crucial, you can create a new "dummy" base that acts as an interface for type checking purposes.