Я создаю довольно сложное веб-приложение, которое начинается с главного меню, в котором пользователь делает свой начальный выбор.Это первый раз, когда я пробовал настоящий ООП-подход с использованием наследования в JavaScript, и я столкнулся с первой проблемой, когда ключевое слово «this» не относится к тому, чего я ожидаю.Я предполагаю, что это является результатом более широкой проблемы с моим подходом ООП / наследования, поэтому я был бы признателен за ответ, который не только говорит мне, как решить эту отдельную проблему, но также предоставляет более глубокие отзывы и советы по моему общему подходу.
Я собираюсь опубликовать код JS только потому, что не думаю, что HTML-код является релевантным, но я, безусловно, могу опубликовать его, если это необходимо.
Следующий код определяет основной классSelect
.Затем он создает подкласс Select
, называемый SelectNum
(посмотрите в конец кода).В SelectNum
я пытаюсь переопределить метод mouseover
для Select
, но не полностью - я хочу сначала вызвать метод super (Select), а затем запустить некоторый дополнительный код.Но когда метод этого подкласса mouseover
запускается, я немедленно получаю следующую ошибку:
"Uncaught TypeError: Невозможно вызвать метод stop из undefined"
По сути, this.shine
не определено.
Для начала я использую следующий код из JavaScript О'Рейли: Полное руководство:
function inherit(p) {
if (Object.create){ // If Object.create() is defined...
return Object.create(p); // then just use it.
}
function f() {}; // Define a dummy constructor function.
f.prototype = p; // Set its prototype property to p.
return new f(); // Use f() to create an "heir" of p.
}
И мой код:
Select = function(el){
return this.init(el);
}
Select.prototype = {
init: function(el){
var that = this;
this.el = el;
this.shine = el.children('.selectShine');
el.hover(function(){
that.mouseover();
},function(){
that.mouseout();
});
return this;
},
mouseover: function(){
this.shine.stop().animate({opacity:.35},200);
},
mouseout: function(){
var that = this;
this.shine.stop().animate({opacity:.25},200);
}
}
//Sub-classes
SelectNum = function(el){
this.init(el);
this.sup = inherit(Select.prototype); //allows access to super's original methods even when overwritten in this subclass
return this;
}
SelectNum.prototype = inherit(Select.prototype);
SelectNum.prototype.mouseover = function(){
this.sup.mouseover(); //call super's method... but this breaks down
//do some other stuff
}
РЕДАКТИРОВАТЬ Ответ от Raynos работал.this.sup.mouseover()
больше не выдает ошибку, и правильный код был запущен.Однако мне действительно нужно создать подкласс SelectNum
с именем SelectLevel
.В отличие от SelectNum
, который переопределяет метод mouseover()
своего суперкласса, SelectLevel
НЕ нужно переопределять метод SelectNum
mouseover()
:
SelectLevel = function(el){
this.init(el);
this.sup = inherit(SelectNum.prototype); //allows access to super's original methods even when overwritten in this subclass
for(var k in this.sup){
this.sup[k] = this.sup[k].bind(this);
}
}
SelectLevel.prototype = inherit(SelectNum.prototype);
С этим кодом метод mouseover()
просто вызывается непрерывно.Я полагаю, это потому, что this
теперь привязан к объекту SelectLevel
, поэтому this.sup
в строке this.sup.mouseover()
в SelectNum
всегда относится к SelectNum
, поэтому он просто продолжает вызывать себя.
Если я удаляю привязку this.sup[k] = this.sup[k].bind(this);
в SelectLevel
, я получаю ошибку Uncaught TypeError: Cannot call method 'mouseover' of undefined
.Похоже, что this.sup.mouseover()
вызывается непрерывно, вызывая метод mouseover
для каждого объекта в цепочке прототипов.Когда он достигает Object
, именно тогда возникает эта ошибка, потому что, конечно, Object
не имеет свойства sup
.
Кажется, что я могу решить эту проблему, удалив this.sup[k] = this.sup[k].bind(this);
связывание в SelectLevel
, а затем перенос this.sup.mouseover()
в оператор if, который сначала проверяет свойство sup
перед вызовом для него метода mouseover()
: то есть if(this.sup !== undefined)
, но на самом деле это не такчувствую себя хорошо.
В конечном счете, я думаю, что мне не хватает чего-то фундаментального в том, как создавать подклассы в JavaScript.Хотя решения этих конкретных проблем проливают некоторый свет на то, как наследование прототипов работает в JS, я действительно думаю, что мне нужно лучшее понимание на более широком уровне.