はじめに
JavaScriptのメソッドなんかをググってる時に、よく以下のようなものを見ますよね。
JSはよくprototypeベースな言語とか言われたりしていますが、prototypeとはなんぞやって疑問に思っていました。
特に今回はその中でも、prototypeチェーンに絞っています。
※もし間違いがあれば、指摘していただけると助かりますm(__)m
すべてのオブジェクトは __proto__ を保持している
以下のコードをブラウザのConsoleなどで実行して見てください。
const dog = {}
console.log(dog)
生成されたオブジェクトdogの中身をconsole.logで確認すると、**_proto_**というプロパティが確認できますよね。
結論を先に言いますと、全てのオブジェクトは、自動的に __proto__ プロパティを保持しています。
ちなみに、 __proto__ プロパティもオブジェクトです。
__proto__ ってなんなのか
結論を先に言います。
オブジェクトの __proto__ プロパティはコンストラクタ関数のprototypeプロパティを参照している。
以下の画像を見てください。
__proto__ は、Object.prototypeということがわかります。
これはつまり、dogの__proto__プロパティがObjectコンストラクタ関数のprototypeプロパティのオブジェクトを参照しているということです。
また、コンストラクタ関数は自動的にprototypeプロパティを保持しています。prototypeプロパティはオブジェクトです。
以下のコードで確認しておきましょう。
//コンストラクタ関数Humanを定義
function Human (name) {
this.name = name;
}
//prototypeオブジェクトに関数をいれる
Human.prototype.hello = function () {
return this.name + 'さん、こんにちは!';
}
var shin = new Human('shin');
console.log(shin.hello()); //=>shinさん、こんにちは!
ちょっと脱線したので、大事なことをまとめます。
内容 | |
---|---|
オブジェクト | 全てのオブジェクトは__proto__プロパティを保持している。 また、__proto__プロパティはコンストラクタ関数のprototypeプロパティを参照している |
コンストラクタ関数 | prototypeプロパティを保持している |
prototypeチェーンとは
まず、言葉で説明します。
prototypeチェーンとは、オブジェクトに必要なプロパティや関数がない場合、__proto__が参照するコンストラクタ関数のprototypeオブジェクトにさかのぼって探すことをいいます。
わかりづらいので、コードで見ていきましょう。
//オブジェクトを生成
const str = new String("");
console.log(str.__proto__ === String.prototype); //=>true
console.log(String.prototype.__proto__ === Object.prototype); //=>true
//prototypeチェーンの最終地点
console.log(Object.prototype.__proto__); //=>null
ここで重要なのは、prototypeプロパティもオブジェクトであるということです。
つまり、__proto__を保持していることになります。
図で表すと以下のようなイメージですね。
例えば、strに対して定義されていないメソッドやプロパティを呼び出すと、Stringコンストラクタ関数のprototypeプロパティを参照し、それでもなければStringコンストラクタ関数のprototypeオブジェクトが持っている__proto__が最終地点のObjectコンストラクタ関数のprototypeプロパティを参照します。それでもない場合は、Objectコンストラクタ関数のprototypeが持っている__proto__がnullが返却されます。