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 |