パーフェクトJavaScript・つまずき(プロトタイプチェーン編)

だいぶ時間が経ってしまったが、話題になった「パーフェクトJavaScript」を読み進めている。とてもわかりやすく、かなり詳しく書いてあって、話題になっていたのも納得。

パーフェクトJavaScript (PERFECT SERIES 4)

パーフェクトJavaScript (PERFECT SERIES 4)

数年ぶりのJavaScript、やっぱりプロトタイプチェーンのところでつまずく。P.143をさらっと流そうとして、わからなくなった。ソースコードは超単純で、次の2行。

function MyClass() {}
var obj = new MyClass();

で、次のように記述がある。なお、ここでの“プロトタイプオブジェクト”とは、オブジェクトの暗黙リンク(__proto__プロパティ)が参照するオブジェクトのこと。

MyClass.prototypeとobj.__proto__は同じオブジェクトを参照します。これがオブジェクトobjのプロトタイプオブジェクトです。紛らわしいですが、MyClass.prototypeの参照オブジェクトはMyClassのプロトタイプオブジェクトではありません(MyClassオブジェクトのプロトタイプオブジェクトは何かわかるでしょうか。答えはFunction.prototypeの参照先オブジェクトです。...(省略)...)。
《パーフェクトJavaScript, 2011/10/25, 技術評論社, p.143》より

おっとっと。
オブジェクト間の関係がわからなくなったので、Google Chrome(バージョンは17)で調べてみることに。しかし、ChromeJavaScriptコンソールは、本当に便利だ。補完までしてくれるし、見やすいし。

なんじゃ、この“Empty”ってのは。しかも、クラス(関数オブジェクト)に見える。でも、prototypeプロパティはないし、直接アクセスもできない。まぁ、実装上のオブジェクトなのだろう。あと、Function.prototypeオブジェクトが、このEmptyオブジェクトになっている(上記書籍のP.171にのっている輩)。こっちは、Firefox 11.0でも、それっぽいのが存在しない。
で、オブジェクト間の関係は、次の絵のようになっているっぽい。

各クラス(関数オブジェクト)は、prototypeプロパティを持っていて*1、それぞれのprototypeオブジェクトを参照している。前述したが、なぜかFunction.prototypeだけは、Emptyオブジェクトを参照している。で、当然constructorプロパティは、Functionクラスを参照している(関数オブジェクトなので)。
で、プロトタイプチェーンの説明は、次の通り。

「プロパティ読み込み時にプロトタイプオブジェクトのプロパティを継承する」のひと言で説明が終わります。
《パーフェクトJavaScript, 2011/10/25, 技術評論社, p.139》より

これで、だいたいすっきりした。

*1:なぜか、Emptyオブジェクトはprototypeプロパティを持っていないが。