Странность прототипического наследования Javascript


Я пытаюсь работать с некоторыми примерами наследования javascript, и я уперся в стену с этим:

function Animal(){}
Animal.prototype.type = "animal";
Animal.prototype.speak = function(){ console.log( "I'm a " + this.type + 
    ". I can't really talk ;)" ); }

function Dog(){}

function F(){}
F.prototype = Animal.prototype;

Dog.prototype = new F();
Dog.prototype.constructor = Dog;
Dog.prototype.type = "Dog";
Dog._super = Animal.prototype;
Dog.woof = function(){ console.log( "Woof!" ); _super.speak(); }

var rover = new Dog();
rover.woof();

Я получаю это, и я понятия не имею, почему:

TypeError: Object #<Dog> has no method 'woof'

Я знаю, что могу поместить не найденный метод в функцию конструктора, но я пытаюсь сделать это с помощью модификации прототипа. Что я здесь делаю не так?

4 4

4 ответа:

Изменение:

Dog._super = Animal.prototype;
Dog.woof = function(){ console.log( "Woof!" ); _super.speak(); }

Кому:

// Dog.prototype._super = Animal.prototype; <- you can remove this line
Dog.prototype.woof = function(){ console.log( "Woof!" ); this.speak(); }

Последняя строка определения псевдокласса Dog неверна. Это должно быть

Dog.prototype.woof = function(){ console.log( "Woof!" ); Dog._super.speak.call(this); }
  1. вы должны определить метод woof как свойство прототипа Dog.
  2. _super доступно только как свойство конструктора Dog.
  3. методы родительского класса следует вызывать в контексте текущего экземпляра.

Таким образом, ваш метод woof фактически является статическим методом (Если вы исходите из java. В основном, он висит от функции Dog, и к нему можно получить доступ без экземпляра Dog. то есть: собака.гав ())

Чтобы заставить его работать с экземпляром собаки, вы хотите убедиться, что это определение прототипа (опять же, с аналогией Java, фактически определение метода экземпляра). Как сказал qwertymik,
Dog.prototype.woof = function(){ console.log( "Woof!" ); this.speak(); }

Тогда вы сможете сделать

var foo = new Dog();
foo.woof();

Может быть, вы хотите сделать это:

Dog.prototype._super = Animal.prototype;
Dog.prototype.woof = function(){ console.log( "Woof!" ); this._super.speak(); }