extendsキーワードを使わない継承のメモ。
function Parent() {} Parent.prototype.foo = function() {}; function Child() {} Child.protoype.bar = function() {}
Parentの継承はChildのインスタンスの暗黙リンク(__proto__)がParent.prototypeも参照できればよい。
単にChild.prototypeにParent.prototypeを代入するとParent.prototypeオブジェクトへの参照が渡る。そのためChild.prototypeの処理はParent.prototypeを変更する。
function Parent() {} Parent.prototype.foo = function() { console.log('foo'); }; function Child() {}; // オブジェクト参照が渡される。 // Child.prototypeへのプロパティはParent.prototypeへ値の設定とイコール。 Child.prototype = Parent.prototype; Child.prototype.bar = function() { console.log('bar'); } var parent = new Parent(); // parentはChild.prototypeのメソッドを実行できる。 parent.bar(); // bar // parentはChildのインスタンスになる console.log(parent instanceof Child) // true;
Child.prototypeにParent.prototypeのインスタンスを設定すればChild.prototypeに対する操作はParent.prototypeを上書きしない(インスタンスに対する操作は暗黙リンクの参照先には影響しない)。このままだとChild.prototype.constructorはParentを参照するので手動でChildに設定する。
function Parent() {} Parent.prototype.foo = function() {}; function Child() {} Child.prototype = (function() { function F() {} F.prototype = Parent.prototype; // Parent.prototypeの「インスタンス」を返す // Child.prototypeにはインスタンスを設定するので上書きしない return new F(); }()); Child.prototype.constructor = Child; Child.prototype.bar = function() { console.log('bar'); } var parent = new Parent(); // parent.bar(); bar is not defined console.log(parent instanceof Child) // false; var child = new Child(); child.bar();
単にChild.prototype = new Parent()は簡単だがParentのインスタンスメソッドも継承されてしまう。またParentが引数を取る場合に問題が起こることがあるので下記のようにする。
Child.prototype = (function() { function F() {} F.prototype = Parent.prototype; return new F(); }());
『テスト駆動開発 JavaScript』p149にはFunctionのprototypeにinherit関数を定義している。
if (!Function.prototype.inherit) { (function() { function F() {} Function.prototype.inherit = function(superFn) { F.prototype = superFn.prototype; this.prototype = new F(); this.prototype.constructor = this; }; }()); }
Christian Johansen著 長尾高弘訳『テスト駆動開発 JavaScript』ASCII
No comments yet.
改行と段落タグは自動で挿入されます。
メールアドレスは表示されません。