I found an example from MDN about super. I learned that super function calls parent's constructor so that the subclass can inherit all the properties/methods from it. However, in the example from MDn, it calls the subclass's constructor.
<script>
class Rectangle {
constructor(height, width) {
this.name = 'Rectangle';
this.height = height;
this.width = width;
}
}
class Square extends Rectangle {
constructor(length) {
super(length, length);
this.name = 'Square';
}
}
let a = new Square(4);
console.log(JSON.stringify(a));
console.log(a.height);
</script>
So we have a Square constructor which extends from Rectangle. My confusion is at the super function which has two arguments from Square but Square is the subclass of Rectangle. Wouldn't it make sense to call super within Square and pass height and width from Rectangle to it so that Square can inherit the height and width from Rectangle since Square is extending Rectangle?
Inheritance happens automatically, you don't need to call super() for this.
super() is used to run the parent class's constructor. When you call new Square(4), this calls the Square constructor automatically with length = 4. But the Rectangle constructor requires two parameters, not the same parameters as the Square constructor. The design of Square is that it's a rectangle whose height and width are the same, so the Square constructor can pass this length parameter to Rectangle to express this idea.
We can't go the other way, because a class can have many different subclasses, and they can each have different relationships with it. There's no way for the superclass to call all possible subclass constructors, since subclasses can be added arbitrarily.
in the example from MDN, it calls the subclass's constructor.
No it doesn't.
Wouldn't it make sense to call
superwithinSquare[…] so thatSquarecan inherit the height and width fromRectanglesinceSquareis extendingRectangle?
That's exactly what's happening.
… and pass height and width from
Rectangleto it
small clarification: it's passing a value (the square side length) as height and width to Rectangle.
The new Square construction calls the new Rectangle construction.
Square is a class derived from Rectangle. The Square constructor calls the parent Rectangle class constructor passing the Square's length as both the Rectangle's width and height. It makes sense to do this because a Square is a Rectangle, but it's a specific kind of rectangle - namely one whose width equals its height.
Note that Square is more specific than Rectangle and Rectangle knows nothing about Square.
The Square constructor exists because a Square is a specialization of a Rectangle. A Square has length (e.g. draw me a square of length 5). It also has a different name ('Square' vs. 'Rectangle'). That means that the Square class needs a constructor, so that you can initialize the things that are special about a Square.
Because you need a Square constructor, that Square constructor must call the Rectangle (super) constructor and it must do so before accessing 'this' (which it does when it sets the square's name) or returning from the derived constructor. This is a requirement of the JavaScript language. If you don't call the super constructor then your code will fail - a ReferenceError will happen, like so:
ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
If you did not need to do any special initialization in a derived class's constructor then you would not even need to declare a constructor function in the derived class. In this case, JavaScript would automatically call the parent class constructor for you when creating an instance of the derived class. But, if you did declare a constructor function in the derived class, even if it was empty, it would have to call the super constructor, otherwise the aforementioned ReferenceError would happen.