2階層以上のプロトタイプチェーンについて
「prototypeオブジェクトにベースオブジェクトインスタンスを設定したら、多重継承ってどうやるんだ??ベースクラスを設定したらサブクラスのprototype書き換えられないじゃん???」
という考えから抜け出せられず、また継承使わずとも十分実装できることもあり、
prototypeとは深くかかわらないようにしてたのですが、今回ようやくスッキリすることができました。
確認用コード
var BaseHoge = (function(){ function BaseHoge() { this.hoge = "ベースオブジェクト"; } BaseHoge.prototype.getHoge = function(){ return this.hoge; }; BaseHoge.prototype.setHoge = function(val){ this.hoge = val; }; return BaseHoge; })(); var SubFoo = (function(){ function SubFoo() { this.foo = "サブオブジェクト"; } SubFoo.prototype = new BaseHoge.prototype.constructor(); SubFoo.prototype.constructor = SubFoo; SubFoo.prototype.getFoo = function(){ return this.foo; }; return SubFoo; })(); var SubSubBar = (function(){ function SubSubBar() { this.bar = "サブサブオブジェクト"; } //BaseHogeインスタンスオブジェクトを //prototypeプロパティにセットする。下記構成になる。 //※コードの通り、prototypeオブジェクトの中身が //SubFooインスタンスオブジェクトになるだけ。 // // prototype { // foo : "サブオブジェクト", // constructor : SubFoo, // __proto__ : SubFoo.prototype // } // SubSubBar.prototype = new SubFoo.prototype.constructor(); //コンストラクタプロパティを時オブジェクトに書き換える //これを行わないと、外からオブジェクトタイプを調べたりすることができなくなってしまう。 //変更後は、下記構成になる。 // // prototype { // foo : "サブオブジェクト", // constructor : SubSubBar, // __proto__ : SubFoo.prototype // } // SubSubBar.prototype.constructor = SubSubBar; //自オブジェクトに持たせる関数の定義 SubSubBar.prototype.getBar = function(){ return this.bar; }; //最終的にはこんな感じ。 //constructorが指す関数と、暗黙リンク(__proto__)が //指す関数が異なる構成だけど、問題なく動作する。 //prototypeオブジェクトも他オブジェクトとなんら変わりない普通の //オブジェクトで、プロトタイプチェーンに必要なプロパティを持っていれば //どんなオブジェクトでも動作する。 // // prototype { // foo : "サブオブジェクト", // getFoo : function(){ ... }, // constructor : SubSubBar, // __proto__ : SubFoo.prototype // } // return SubSubBar; })(); console.clear(); //インスタンスオブジェクトの中身はこんな感じ //{ // bar : "サブサブオブジェクト", // prototype : { // foo : "サブオブジェクト" // getFoo : function(){ ... }, // constructor : SubSubBar, // __proto__ : SubFoo.prototype // }, // constructor : SubSubBar, // __proto__ : SubSubBar.prototype //} // var obj = new SubSubBar(); console.dir(obj); //obj.__proto__.__proto__.__proto__.setHoge()を実行する。 //実行後のオブジェクトの中身は以下な感じ。 // //{ // bar : "サブサブオブジェクト", // hoge : "ほげ~", // prototype : { ... } // constructor : SubSubBar, // __proto__ : SubSubBar.prototype //} // obj.setHoge("ほげ~"); //メソッド場所の検索、処理フローはsetHoge()と同様。 console.log("getHoge() : ", obj.getHoge());
参考書籍
開眼! JavaScript ―言語仕様から学ぶJavaScriptの本質
- 作者: Cody Lindley,和田祐一郎
- 出版社/メーカー: オライリージャパン
- 発売日: 2013/06/19
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る