プロトタイプチェーン

ふとJavaScriptに入門してみたところ、プロトタイプチェーンなるものが現れた。

var SomeObject = function(){};
SomeObject.prototype.someMethod = function() { print("some method!\n"); };
var AnotherObject = function(){};
AnotherObject.prototype = new SomeObject();

newしたものを入れることでワークするらしい。なんで?

通常のプロトタイプはこう。

var SomeObject = function(){};
SomeObject.prototype.someMethod = function() { print("some method!\n"); }; 
SomeObject.prototype.anotherMethod = function() { print("another method!\n"); }; 

あるいは、こういう書き方もある、と紹介されてる。

var SomeObject = function(){};
SomeObject.prototype = {
  someMethod : function() { print("some method!\n");},
  anotherMethod : function() { print("another method!\n");}
}; 

それがどうして唐突にnewに?と疑問を抱いた。

 
このままでは覚えられそうにないと思ったので、spidermonkeyを使って色々試してみた。

まずはコンストラクタの動作。

js> var Hoge = function(hoge){
  this.hoge = hoge;
};
js> Hoge
function (hoge) {
    this.hoge = hoge;
}
js> var hoge = new Hoge(2);
js> hoge;
[object Object]
js> new Hoge(2)
[object Object]
js> Hoge(2)
js>

コンストラクタは関数で、new + コンストラクタ によって返されるのは辞書(あるいは連想配列)。
で、コンストラクタに正しい引数を与えても何も返らない。これはコンストラクタを単に関数として判断しても何も返ってないから。return文を入れてれば対応したものが返る。

 

続いて生成されたオブジェクトについて見てみた。

js> var Hoge = function(hoge){
  this.a = hoge + " a";
  this.b = hoge + " b";
  this.print_it = function(){
    print (this.a + " " + this.b);
  };
};
js> Hoge
function (hoge) {
    this.a = hoge + " a";
    this.b = hoge + " b";
    this.print_it = function () {print(this.a + " " + this.b);};
}
js> hoge = new Hoge("wow");
[object Object]
js> for (key in hoge) {print(key)}
a
b
print_it
js> for (key in hoge) {print(key + " = " + hoge[key])}
a = wow a
b = wow b
print_it = function () {
    print(this.a + " " + this.b);
}
js>

オブジェクトは辞書だと納得。

 

で、最後に、辞書の宣言。

js> var dic = {
  "a" : "ahoge",
  "b" : "bhoge",
  c   : "choge"
}
js> dic["a"]
ahoge
js> dic.b
bhoge
js> dic["c"]
choge

辞書はオブジェクトと等価っぽい。

 

てわけで、

要は全部が辞書だからあんな書き方が許容されるみたいね。
prototypeの参照を追っかけるのは言語の仕様に入っちゃってるのかな、追いかけ方は今のところ見当もつかない。