2015-01-08 5 views
1

Можно ли вызвать обычный метод из прототипа, если он был переопределен? Обратите внимание, что в данном примере первый метод eat() вызывается из тела функции Animal - это требование.Javascript - вызов дочернего метода из метода прототипа

Animal = function(){ 
    this.eat(); 
}; 

Animal.prototype.eat = function() { 
    console.log("All animals eat"); 
}; 

Bear = function(){ 
    Animal.call(this); 
    this.goToSleep = function(){ 
     console.log("Bears go to sleep after they eat"); 
    } 
}; 

Bear.prototype = Object.create(Animal.prototype); 

Bear.prototype.eat = function() { 
    console.log("Bears eat honey"); 
    this.goToSleep(); //returns 'undefined is not a function' 
    //How do I invoke this.goToSleep() ? 
}; 

var winnie = new Bear(); 
+1

Почему бы не определить его как «Bear.prototype.goToSleep»? – loganfsmyth

+0

Вы не должны смешивать функциональный шаблон с образцом прототипа. Определите все методы прототипа или определите их все на каждом экземпляре. (Шаблон прототипа предпочтительнее, потому что он избегает дублирования.) – bgoldst

ответ

1

Вопрос заключается в том, что ваш медведь не имеет метод goToSleep когда eat первым получает вызывается.

При вызове Animal.call(this) в вашем Bear конструктору он затем вызывает eat - который находится на Bear.prototype и вызывается. Затем eat пытается вызвать goToSleep, но goToSleep - это метод экземпляра, который вы еще не добавили (помните, что мы все еще на Animal.call мы еще не достигли this.goToSleep = function()).

Если у вас есть хороший повод, goToSleep должен быть метод прототип, а, так же, как eat:

Bear.prototype.goToSleep = function(){ 
    console.log("Bears go to sleep after they eat"); 
}; 

Это просто работать, как вы хотите.

В качестве альтернативы, если goToSleepимеет быть методом экземпляра (так как он необходим доступ к некоторым частным состоянием вы создаете в конструкторе), а затем просто изменить порядок ваших Animal.call и this.goToSleep линий:

this.goToSleep = function() // etc. 
Animal.call(this); 
+0

Шон, спасибо за подробный и проницательный ответ. Вы сделали мой день! Проблема заключалась в том, что реальный эквивалент проекта goToSleep() должен получить доступ к методам и свойствам функции базового класса (т. Е. Animal), поэтому он не может быть прототипом. Переключение линий делало магию! –

+0

В тех случаях, что я обычно делаю, выставляем супер-прототип на объект через метод SubConstructor.prototype. $ Super = SuperConstructor.prototype'. Тогда я могу просто сделать это. $ Super.someMethod.call (это, arg1, arg2, argN) '. –

Смежные вопросы