Reputation: 5848
I am trying to understand Javascript's prototypical inheritance model but there seems to be something I am missing. I have created the following set of objects:
function Dog() {
this.legs = 4;
this.arms = 0;
}
Dog.prototype.describe = function() {
console.log("Has " + this.legs + " legs and " + this.arms + " arms");
}
function Schnauzer(name) {
Dog.call(this);
this.name = name;
}
Schnauzer.prototype.describe = function() {
console.log(this.name + " is a Schnauzer with a shaggy beard");
Dog.prototype.describe(this);
}
var my_dog = new Schnauzer("Rupert");
my_dog.describe();
My expectation here is that this would output:
Rupert is a Schnauzer with a shaggy beard
Has 4 legs and 0 arms
however this is what i actually get:
Rupert is a Schnauzer with a shaggy beard
Has undefined legs and undefined arms
Upvotes: 0
Views: 67
Reputation: 370729
With
Dog.prototype.describe(this);
you're calling the describe
method with a calling context (a this
value) of Dog.prototype
, and passing the dog instance as the first argument. But describe
doesn't accept any arguments, and it tries to take properties from this
.
Do Dog.prototype.describe.call(this);
instead, to call the method with a this
value of the dog instance:
function Dog() {
this.legs = 4;
this.arms = 0;
}
Dog.prototype.describe = function() {
console.log("Has " + this.legs + " legs and " + this.arms + " arms");
}
function Schnauzer(name) {
Dog.call(this);
this.name = name;
}
Schnauzer.prototype.describe = function() {
console.log(this.name + " is a Schnauzer with a shaggy beard");
Dog.prototype.describe.call(this);
}
var my_dog = new Schnauzer("Rupert");
my_dog.describe();
Still, this is kind of ugly, since you have to use .call
just to get to a method that, in a normal situation, would be higher up on the prototype chain of the current object. If possible, you might consider re-naming your Schnauzer.prototype.describe
method, so it doesn't overshadow the Dog.prototype
method:
function Dog() {
this.legs = 4;
this.arms = 0;
}
Dog.prototype.describe = function() {
console.log("Has " + this.legs + " legs and " + this.arms + " arms");
}
function Schnauzer(name) {
Dog.call(this);
this.name = name;
}
Schnauzer.prototype = Object.create(Dog.prototype);
Schnauzer.prototype.describeSchnauzer = function() {
console.log(this.name + " is a Schnauzer with a shaggy beard");
this.describe();
}
var my_dog = new Schnauzer("Rupert");
my_dog.describeSchnauzer();
Or use class
syntax and super
:
class Dog {
legs = 4;
arms = 0;
describe() {
console.log("Has " + this.legs + " legs and " + this.arms + " arms");
}
}
class Schnauzer extends Dog {
constructor(name) {
super();
this.name = name;
}
describe() {
console.log(this.name + " is a Schnauzer with a shaggy beard");
super.describe();
}
}
var my_dog = new Schnauzer("Rupert");
my_dog.describe();
Upvotes: 3