ユーザーが最初の選択を行うメイン メニューから始まる、かなり複雑な Web アプリを構築しています。JavaScript で継承を使用して真の OOP アプローチを試したのはこれが初めてで、「this」キーワードが期待するものを参照していないという最初の問題に遭遇しました。これは、OOP/継承アプローチのより広範な問題の結果であると推測しているため、この個々の問題を解決する方法を教えてくれるだけでなく、一般的なアプローチに関するより深いフィードバックとアドバイスを提供してくれる回答をいただければ幸いです。
HTML は関係ないと思うので、JS コードのみを投稿しますが、必要に応じて投稿することもできます。
次のコードは、メイン クラスを定義しますSelect
。Select
次に、 calledのサブクラスを作成しますSelectNum
(コードの最後を見てください)。では、 のメソッドSelectNum
をオーバーライドしようとしていますが、完全ではありません。最初にスーパーの (Select の) メソッドを呼び出してから、追加のコードを実行したいと考えています。しかし、このサブクラスのメソッドが実行されると、すぐに次のエラーが発生します。mouseover
Select
mouseover
「キャッチされていない TypeError: 未定義のメソッド 'stop' を呼び出せません」
基本的にthis.shine
未定義です。
まず、O'Reilly の JavaScript: The Definitive Guide の次のコードを使用しています。
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
}
EDIT
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);
のバインディングを削除し、メソッドを呼び出す前に最初にプロパティをチェックする if ステートメントで をSelectLevel
ラップすることで、これを解決できるようです。this.sup.mouseover()
sup
mouseover()
if(this.sup !== undefined)
最終的に、JavaScript でサブクラス化する方法について、何か基本的なことが欠けていると思います。これらの特定の問題に対する解決策は、プロトタイプの継承が JS でどのように機能するかを明らかにしますが、より広いレベルでよりよく理解する必要があると本当に思います。