Class extends Object?
As we know, all objects normally inherit from Object.prototype and get access to âgenericâ object methods like hasOwnProperty etc.
For instance:
class Rabbit {
constructor(name) {
this.name = name;
}
}
let rabbit = new Rabbit("Rab");
// hasOwnProperty method is from Object.prototype
alert( rabbit.hasOwnProperty('name') ); // true
But if we spell it out explicitly like "class Rabbit extends Object", then the result would be different from a simple "class Rabbit"?
Whatâs the difference?
Hereâs an example of such code (it doesnât work â why? fix it?):
class Rabbit extends Object {
constructor(name) {
this.name = name;
}
}
let rabbit = new Rabbit("Rab");
alert( rabbit.hasOwnProperty('name') ); // Error
First, letâs see why the latter code doesnât work.
The reason becomes obvious if we try to run it. An inheriting class constructor must call super(). Otherwise "this" wonât be âdefinedâ.
So hereâs the fix:
class Rabbit extends Object {
constructor(name) {
super(); // need to call the parent constructor when inheriting
this.name = name;
}
}
let rabbit = new Rabbit("Rab");
alert( rabbit.hasOwnProperty('name') ); // true
But thatâs not all yet.
Even after the fix, thereâs still an important difference between "class Rabbit extends Object" and class Rabbit.
As we know, the âextendsâ syntax sets up two prototypes:
- Between
"prototype"of the constructor functions (for methods). - Between the constructor functions themselves (for static methods).
In the case of class Rabbit extends Object it means:
class Rabbit extends Object {}
alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) true
alert( Rabbit.__proto__ === Object ); // (2) true
So Rabbit now provides access to the static methods of Object via Rabbit, like this:
class Rabbit extends Object {}
// normally we call Object.getOwnPropertyNames
alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // a,b
But if we donât have extends Object, then Rabbit.__proto__ is not set to Object.
Hereâs the demo:
class Rabbit {}
alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) true
alert( Rabbit.__proto__ === Object ); // (2) false (!)
alert( Rabbit.__proto__ === Function.prototype ); // as any function by default
// error, no such function in Rabbit
alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // Error
So Rabbit doesnât provide access to static methods of Object in that case.
By the way, Function.prototype also has âgenericâ function methods, like call, bind etc. They are ultimately available in both cases, because for the built-in Object constructor, Object.__proto__ === Function.prototype.
Hereâs the picture:
So, to put it short, there are two differences:
| class Rabbit | class Rabbit extends Object |
|---|---|
| â | needs to call super() in constructor |
Rabbit.__proto__ === Function.prototype |
Rabbit.__proto__ === Object |