inherit
継承
インスタンスのメソッドを呼び出されたとき、prototypeからメソッドを探すので、インスタンスのコンストラクタが持っている prototype を適当な別のクラスのインスタンスに書き換えれば、その置き換えたクラスのメソッドを全て利用することができる。
ClassBのprototypeをClassAのインスタンスに置き換えることで、ClassBのインスタンスがClassAのメソッドを呼べるようになる。
function ClassA(){ } ClassA.prototype.execute = function(){ window.alert("hoge"); } function ClassB(){} ClassB.prototype = new ClassA(); new ClassA().execute(); // hogeと表示 new ClassB().execute(); // hogeと表示
オーバーライド
継承した親クラスのメソッドと同じ名前のメソッドを定義するだけ。
function ClassA(){ this.hoge = "executeメソッド実行。\n\n"; } ClassA.prototype.execute = function(){ window.alert( this.hoge + "Aのメソッド"); } function ClassB(){} ClassB.prototype = new ClassA(); ClassB.prototype.execute = function(){ window.alert( this.hoge + "Bでオーバーライドされたメソッド"); } new ClassA().execute(); new ClassB().execute();
実際の処理は次のようになる。オーバーライド前のメソッド呼び出しは
自分のexecuteメソッドを探す →見つからないので prototype の execute を探す →見つからないので prototype の prototype の execute を探す →見つかったのでexecute実行
これがオーバーライドによって、
自分のexecuteメソッドを探す →見つからないのでprototype の executeを探す →見つかったのでexecute実行
と変化したのである。なお、このような prototype 参照の連鎖をプロトタイプチェインと呼ぶ
親クラスのメソッドを呼ぶ。
親クラスのメソッドを呼び出すにはcallメソッドを使います。
callメソッドは Functionオブジェクトのメソッドで、第一引数に渡したオブジェクトのメソッドとして自分自身を実行するものです。以下の例では、prototype の execute メソッドを自分自身のメソッドとして実行します。そうしないとClassA.execute で this.hoge が undefined になってしまいます。
function ClassC(){} ClassC.prototype = new ClassA(); ClassC.prototype.execute = function(){ this.hoge = "Cクラスから親クラスのメソッドを呼ぶ"; this.constructor.prototype.execute.call(this , arguments); } // Cクラスから親クラスのメソッドを呼ぶAのメソッド と表示される new ClassC().execute();
なお、JavaScriptにはsuperキーワードはありませんが、予約語なので変数名などに使用することはできません。
constructorプロパティ
this.constructor
って function ClassC(){}
じゃないの、上のコードって自分自身を呼び出してスタック使い果たすまで再帰しないの?と思うかもしれませんが、そうはなりません。constructor は インスタンス固有のプロパティではなく、クラスを定義した時に prototype にセットされるプロパティです。
new ClassC().constructor; new ClassC().hasOwnProperty("constructor"); // インスタンス固有のプロパティではない
this.constructor
にアクセスするとconstructorプロパティは、プロトタイプチェインを辿って、ClassC の prototype、すなわちClassA の インスタンスから取得しようとします。ClassAのインスタンスもconstructorを持ってないので、さらにプロトタイプチェインを辿って、ClassA の prototype から取得されます。よって 、this.constructor
は、function ClassA(){}
になります。