JavaScript でオブジェクトを継承してみる
最近 __proto__ プロパティを使うとオブジェクトの継承ができることを知った。
- コア・JavaScript ( JavaScript. The Core. ) - oogattaの勉強日記 http://d.hatena.ne.jp/oogatta/20101003/1286099289
- すっごいわかりやすい。やっぱ図を描くの大事!
シンプルに書くとこんな感じ。ちなみにサンプルコードは Rhino で実行・確認しました。printが使えない環境ではalertなどに置き換えてね。
var a = {}; a.v = "abcd"; a.f = function() { return this.v; }; var b = {}; b.__proto__ = a; // a オブジェクトを継承 print( b.f() ); // 親オブジェクト a の f() が呼ばれる
実行結果
abcd
これを応用してコンストラクタ(っぽい関数)を呼び出してオブジェクトのインスタンスをつくる方法を思いついた。継承できるし、メソッドオーバーライトもできるよ。
こんな感じ。
var createA = function(n) { // private var v = n; // public var _public = {}; // _public.__proto__ = Object.prototype; // Object.prototype を参照 _public.f = function() { return v * 10; }; _public.g = function() { return v * 100; }; return _public; }; var createB = function(n) { // public var _public = {}; _public.__proto__ = createA(n); // A オブジェクトを継承 _public.g = function() { return _public.__proto__.g() * 2; }; // g メソッドをオーバーライド return _public; }; var a = createA(1); // A オブジェクトのインスタンス a を生成 var b = createB(1); // B オブジェクトのインスタンス b を生成 print( a.f() ); print( a.g() ); print( b.f() ); print( b.g() );
実行結果
10 100 10 200
前から new 演算子と prototype プロパティを使って似たようなことができるのは知ってたけど直感的じゃないので使いたくなかったんだよね。
var A = function(n) { this.v = n; }; A.prototype.f = function() { return this.v + this.v; }; var B = function(n) { this.v = n }; B.prototype = new A(); // A オブジェクトを継承 (new A()ってなに?きもっ) var b = new B(1); print( b.f() ); print(b instanceof B); // B オブジェクトのインスタンスか判別 print(b instanceof A); // A オブジェクトを親に持つインスタンスか判別
実行結果
2 true true
__proto__を使えば new や prototype を使わず直感的に記述できてうれしい(おいらは)。instanceof でオブジェクトの継承関係を判別できないのは残念だけど。。(ひょっとして、できる?)