JavaScriptのプロトタイプベースのオブジェクト指向について、調べたこと

jsは(ES6より前は)クラスを持たないオブジェクト指向言語である。クラスの代わりに、プロトタイプというプロパティを作り、そのプロパティを複数インスタンスで共有する。そのためプロトタイプベースのオブジェクト指向言語といわれている。

jsの全てのオブジェクト(関数やプロパティの集合)は、__proto__プロパティに「継承したオブジェクト」のメモリアドレスを格納できる。

jsの全てのオブジェクトは、Object.prototypeを継承している。そのため、__defineSetter__, __defineGetter__, toString, hasOwnPropertyなどのメソッドをデフォルトで使うことができる。 下記はコンソールログでオブジェクトを生成し、継承元のObject.prototypeを表示している。

f:id:bambinya:20150725205934p:plain

 

コンストラクタ関数とnew演算子を使ったオブジェクト生成の例

js create object with new Object()

 

生成したオブジェクトの中身をコンソールで見てみよう!

chromeのコンソールログでまったく同じコードを入力する。

f:id:bambinya:20150725202547p:plain

 

コンストラクタPersonから生成したperson1は、name, a, __proto__の3つのプロパティを持つ。__proto__プロパティには、コンストラクタ関数Personのprototypeのメモリアドレスを格納する。このメモリアドレスを元に、person1はコンストラクタ関数が持つoutputName()を使用することができる。

f:id:bambinya:20150725202911p:plain

図で描くとこんな感じ。person1の__proto__にはPerson.prototypeのメモリアドレスが格納されており、Person.prototypeのプロパティの参照が可能である。

f:id:bambinya:20150725220901p:plain

 

一方、person2が持つプロパティはnameと__proto__のみである。person2.aが定義されていない場合は、継承元である上位のPerson.prototypeを探索しに行く。もし見つからなければ最上位の Object.prototype までプロパティを探索しにいく。

f:id:bambinya:20150725210159p:plain

 

オブジェクトの継承過程をたどる

Personコンストラクタから生成したオブジェクトperson1は、コンストラクタ関数とは別のメモリに格納される。オブジェクトによって、プロトタイプチェーンが異なる。

オブジェクトperson1は、下記のようになる。

 person1 < Person < Object < null (上位の継承オブジェクトがない)

コンストラクタPersonは、下記のようになる。

 Person < Empty < Object < null (上位の継承オブジェクトがない)

 

コンソールで見てみよう。

f:id:bambinya:20150725211359p:plain

f:id:bambinya:20150725211713p:plain

function Empty()のプロトタイプにはapplyやcallメソッドが定義されている。

f:id:bambinya:20150725212118p:plain