Reputation: 259
I came across this example while reading the prototype.
function Animal(){
this.name = 'Animal'
}
var animal1 = new Animal();
function Rabbit(){
this.canEat = true;
}
Rabbit.prototype = new Animal();
var r = new Rabbit();
console.log(r.constructor)
And the console is giving me Animal as the output for r.constructor, which is a little confusing as the constructor property should have returned Rabbit as r is created by invoking Rabbit with the new operator.
Also, if I invoke the Rabbit function before assigning the prototype it gives me the desired result.
Upvotes: 1
Views: 112
Reputation: 1075915
Objects inherit constructor
from their prototype (typically); they get their prototype from the prototype
property of the constructor function that creates them when they're created (if they're created by a constructor function). Rabbit.prototype
's constructor
is incorrect, because of this:
Rabbit.prototype = new Animal();
That calls Animal
to create a new instance, and assigns that instance as Rabbit.prototype
. So its constructor
, inherited from Animal.prototype
, is Animal
. You've replaced the default object that used to be on Rabbit.prototype
(which had constructor
set to Rabbit
).
In general, that Rabbit.prototype = new Animal()
is not the best way to set up inheritance. Instead, you do it like this:
Rabbit.prototype = Object.create(Animal.prototype);
Rabbit.prototype.constructor = Rabbit;
and then in Rabbit
:
function Rabbit() {
Animal.call(this); // ***
this.name = "Rabbit"; // Presumably we want to change Animal's deafult
this.canEat = true;
}
Three changes there:
Animal
when setting up the inheritance, we just create a new object that uses Animal.prototype
as its prototype, and put that on Rabbit.prototype
.constructor
on the new object we've assigned to Rabbit.prototype
.Animal
when initializing the instance (in Rabbit
).Live Example:
function Animal(){
this.name = 'Animal'
}
var animal1 = new Animal();
function Rabbit() {
Animal.call(this); // ***
this.name = "Rabbit"; // Presumably we want to change Animal's deafult
this.canEat = true;
}
Rabbit.prototype = Object.create(Animal.prototype);
Rabbit.prototype.constructor = Rabbit;
var r = new Rabbit();
console.log(r.constructor);
Or, of course, use ES2015+ class
syntax, which handles this plumbing for you (along with a few other benefits).
class Animal {
constructor() {
this.name = "Animal";
}
}
class Rabbit extends Animal {
constructor() {
super();
this.name = "Rabbit";
this.canEat = true;
}
}
const r = new Rabbit();
console.log(r.constructor);
Upvotes: 5