I have the following code:
class Polygon {
constructor() {
this.name = "Polygon";
}
}
class Rectangle {
constructor() {
this.name = "Rectangle";
}
}
class Square extends Polygon {
constructor() {
super();
}
}
Object.setPrototypeOf(Square, Rectangle);
const instance = new Square();
console.log(instance.name); // Rectangle
My understanding is:
Instance__proto__
: Points to Square.prototype to inherit instance methods.Subclass.__proto__
: Points to Rectangle to inherit static methods and properties.Square.prototype.__proto__
: Points to Polygon.prototype to inherit the parent class’s instance methods.
My Question:
In the code above, after using Object.setPrototypeOf(Square, Rectangle)
, the Square._proto_
is now pointing to Rectangle and not Polygon for all static properties. And for inheriting all the other methods Square.prototype._proto_
points to Polygon.prototype
. So, then I expect super()
in Square to invoke Polygon’s constructor, since Square extends Polygon. However, it seems like super() is invoking Rectangle’s constructor instead. I’m confused now, what all gets changed when Object.setPrototypeOf(Square, Rectangle)
is run, seems like there is a gap in my understanding.
2
Answers
I’ll leave off most details concerning classes, prototypes, and what not – you can read about them at MDN’s object prototypes and classes pages.
However: Generally, in JS a
class
is not pre-backed like it is in other languages. JS allows to alter a class’ definition at runtime, so the call tosuper()
can point to different constructors throughout script execution if you want that. In that regards it is more like a class in Common Lisp and not like one in Java.When you write
it is conceptually the same as if you write
So when you write
it can (again conceptually) be translated into
and that means that at the time
is executed, it points to
Rectangle.prototype.constructor()
in the context of a Square instance. Hence you end up withthis.name
being"Rectangle"
.What’s missing is where the value of
super
is coming from.A base class (as in not extending another class) is prototyped on
Function.prototype
. For exampleA class extending another causes two things to happen:
The extended class is prototyped on the class being extended and not on
FUNCTION.prototype
. For exampleThe extended class’s
prototype
property is prototyped on theprototype
property of the class extended. For exampleNote the
constructor
value inherited from an extended class’sprototype
is not modified and remains set to the extended class object. I.E.This has ramifications: the super class of an extended object can’t be determined from the
constructor
property inherited by instances of the the extended class.__proto__
property of an extended class is its super class object.This code shows the effects of changing the
__proto__
property of an extended class as an experiment to see what happens.In all of the above, the static
className
property is inherited fromSquare.__proto__
,name
is set by the constructor called assuper()
andconstructor.name
is inherited from the first object in the inheritance chain of an instance.