Dallas Caley
Dallas Caley

Reputation: 5848

Why does my child class not inherit properties from the parent in Javascript?

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

Answers (1)

CertainPerformance
CertainPerformance

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

Related Questions