Почему мой дочерний класс не наследует свойства от родительского в Javascript? - PullRequest
0 голосов
/ 20 января 2020

Я пытаюсь понять прототипную модель наследования Javascript, но, похоже, что-то мне не хватает. Я создал следующий набор объектов:

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();

Я ожидаю, что это выдает:

Rupert is a Schnauzer with a shaggy beard
Has 4 legs and 0 arms

однако вот что я на самом деле получаю:

Rupert is a Schnauzer with a shaggy beard
Has undefined legs and undefined arms

1 Ответ

3 голосов
/ 20 января 2020

С

Dog.prototype.describe(this);

вы вызываете метод describe с контекстом вызова (значение this) Dog.prototype и передаете экземпляр dog в качестве первого аргумента. Но describe не принимает никаких аргументов и пытается взять свойства у this.

Do Dog.prototype.describe.call(this);, чтобы вызвать метод со значением this экземпляра dog:

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();

Тем не менее, это довольно уродливо, поскольку вы должны использовать .call только для того, чтобы добраться до метода, который в обычной ситуации был бы выше по сравнению с прототип цепочки текущего объекта. Если возможно, вы можете переименовать свой метод Schnauzer.prototype.describe, чтобы он не омрачал метод Dog.prototype:

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();

Или используйте class синтаксис и 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();
...