JavaScriptをしっかり勉強 vol.3 プロトタイプ参照
- プログラム
- date 2014.05.10 tag JavaScript
JavaScriptを勉強したことを書いていくエントリーvol.3です。今回はJavaScriptの特徴的なものであるプロトタイプ参照についての内容です。プロトタイプ参照を考える上でnew式の説明から始めています。
new式でのオブジェクトの生成
プロトタイプ参照の前に最初はオブジェクトのお話。vol.1でオブジェクトの生成方法としてリテラル記法を書きましたが(「var obj = {}」こんなヤツ)オブジェクトの生成する別の方法として「new」式があります。プロトタイプ参照にはnew式が関連くるので先に説明します。
new式
「new」を使って関数を実行することによってオブジェクトが作成され、その参照を変数に代入することができます。
他のオブジェクト指向の言語では馴染みが深いクラスのインスタンス化と似たような動きをするものです。ただしJavaScriptにはクラスは存在せず、関数をnewすることになります。
JS new式のサンプルコード
このコードでは、関数「BaseObject」に対してnewを実行して独立したオブジェクトを作成しています。
関数内部のコードでは「this.creator」と記載していて、このthisが指すのはnew式で新しく作成されるオブジェクトのプロパティとなります。グローバルオブジェクトのプロパティwindow.creatorを参照するではなく、newの特別な挙動によって作成するオブジェクトに関連付けられます。
なおnew式で呼び出す関数のことを「コンストラクタ」と呼び、慣習的な命名では頭文字が大文字のCamelCase記法を用います。サンプルコードでは「BaseObject」と命名の区切りを大文字にする記法です。
※newの特別な挙動に関してはこちらのスライドが大変勉強になりましたので紹介させていただきます。
リテラル記法との使い分け
オブジェクトを作成するにはnew式、リテラル記法の2つがありますが内部処理が違うため使い分けが必要です。
リテラル記法では1つのオブジェクトを自分で記述するのに使います。たとえば関数の引数としてまとめるなど、一時的にデータのまとまりを作成するなどに使うのがいいでしょう。
// 検索パラメータを指定
var param = {
type : 'drink',
keyword : 'コーヒー'
};
// 検索パラメータオブジェクトを引数に指定
findItem(param);
対してnew式ではパラメータが異なるオブジェクトを複数作成する、というように汎用性を想定した用途で使います。先ほどのサンプルコードのように、指定する値を元に独立したオブジェクトを作るという想定がいいでしょう。
またnew式を使うことによって本エントリーの主旨であるプロトタイプ参照による継承が可能なので、オブジェクト指向に基づいたプログラムを記述する際にはnew式を使うのが一般的です。
プロトタイプ参照
new式の基本を押さえたうえでやっと本題のプロトタイプ参照に入ります。
JavaScriptでオブジェクト指向プログラミングの継承と同様な、差分プログラミングを実装する仕組みとしてプロトタイプ参照があります。オブジェクトが持っていないメソッドやプロパティを参照するときでも、プロトタイプを参照して呼び出すことができます。
JS プロトタイプ参照のサンプルコード
ここではExtendedObjectというオブジェクトを作成しており、この定義では「text」プロパティしか保持していませんが「creator」プロパティを参照して出力することができています。
// textプロパティしか定義していない
function ExtendedObject() {
this.text = 'create!';
}
// creatorプロパティを参照できる
var obj = new ExtendedObject();
result.innerHTML = obj.creator + '<br>';
ちなみにconsole.logでobjを確認したらこんな感じ。
{ text=”create!”, creator=”iced”}
これはプロトタイプチェーンというものでコンストラクタ(関数)がデフォルトで持っている「prototype」プロパティをたどっていき、自分自身のプロパティのように扱うことができる仕組みです。
オブジェクト:objに「creator」というプロパティが存在しなければ、18行目で記載しているprototypeを参照します。ここではnew式「new BaseObject(param)」によりprototypeプロパティにcreatorプロパティを持ったオブジェクトを代入しています。
prototypeプロパティはオブジェクトを保持するので次のようなコードを静的に記載したのと同じです。
ExtendedObject.prototype = {
creator : 'iced'
};
自身のオブジェクトにプロパティが存在しなかったらnewしたコンストラクタのprototypeプロパティをたどる下図のようなイメージです。new式で作られたオブジェクトはコンストラクタのprototypeプロパティへの暗黙参照を持っています。

リテラル記法によるプロトタイプチェーン
new式ではこのように継承関係を作っていき、差分プログラミングを実装することが可能です。
ただしプロトタイプチェーンはnew式でないと発生しない訳ではないです。プロトタイプチェーンがたどる最終地は組み込みのコンストラクタ:Objectです。そのためObjectに定義されているtoString()等はオブジェクトリテラルで作成したオブジェクトでも使うことができます。
リテラル記法でオブジェクトを作成するときには「new Object();」がされている挙動になります。