はじめに
JavaScriptのプロトタイプチェーンの触りの部分についてまとめました。
プロトタイプ
- JavaScriptのオブジェクトは、プロトタイプと呼ばれる別のオブジェクトへのリンクを持つプライベートプロパティ(クラスの外部から参照することができないプロパティ。)を持っている
プロトタイプチェーン
- あるオブジェクトのプロトタイプとして指されているオブジェクト(プロトタイプオブジェクト)もプロトタイプを持ち、それは
null
をプロトタイプとするオブジェクトに到達するまで続く。これをプロトタイプチェーンという -
null
はプロトタイプを持たない - あるオブジェクトのプロパティを参照すると、そのオブジェクトだけでなく、プロトタイプチェーンを辿って行き、一致する名前のプロパティが得られるか、プロトタイプチェーンの終端に到達するまでプロパティの探索が行われる
- プロトタイプチェーンの中に参照しようとするプロパティがない場合、
undefined
を返す - あるオブジェクトでプロトタイプチェーン上のプロパティと同名のプロパティを定義すると、そのオブジェクトのプロパティが参照される
コンストラクタ関数
- 複数のオブジェクトに共通なプロパティを定義したい場合、それらのオブジェクトに同じプロトタイプを持たせ、そのプロトタイプに共通に使いたいプロパティを定義するのが効率的
- コンストラクタ関数を用いて実現する。
- コンストラクタ関数は
new
を使って呼び出される。 - コンストラクタ関数から生成されたオブジェクトをインスタンスという
- インスタンスは、そのコンストラクタ関数の
prototype
プロパティを自動的にプロトタイプとして持つ - 以上より、
Constructor.prototype
にプロパティを定義すれば、そのコンストラクタ関数から生成されたインスタンスに共通のプロパティを持たせることができる - また、Constructor.prototypeは既定で
constructor
というコンストラクタ関数自身を参照するプロパティを持つので、あらゆるインスタンスから元のコンストラクタにアクセスできる - 以下は、mdnからの引用
mdnからの引用// コンストラクター関数 function Box(value) { this.value = value; } // Box() コンストラクターで作成されたすべてのボックスには、 // 以下のプロパティがあります。 Box.prototype.getValue = function () { return this.value; }; const boxes = [new Box(1), new Box(2), new Box(3)];
暗黙的なコンストラクタ
- オブジェクトのリテラルには、自動的に
Object.prototype
がプロトタイプとして設定される - 配列リテラルでは、自動的に
Array.prototype
がプロトタイプとして設定される - RegExpリテラルには、自動的に
RegExp.prototype
がプロトタイプとして設定される
Object.create()
-
Object.create()
を呼び出すと、新しいオブジェクトが生成される -
Object.create()
の最初の引数が、新しいオブジェクトのプロトタイプとなる
注意点
- プロトタイプチェーンの長さはパフォーマンスに影響する。あまりに長ければ、それを分割すること
- ネイティブのプロトタイプは、決して拡張してはいけない(新しいJavaScriptの機能との互換性をとる場合のみが例外)