JavaScript プロトタイプチェーンとは(継承)

目次

プロトタイプチェーンとは

オブジェクトが、上の階層のオブジェクトをたどってプロパティやメソッドを探す仕組みです。

JavaScriptでは、そのオブジェクト自身に存在しないプロパティやメソッドを呼び出すと、
「親(prototype)」を順にさかのぼって探します。

このたどるつながりのことをプロトタイプチェーンと呼びます。

継承

プロトタイプチェーンは、継承を実現する仕組みです。

Javascriptではクラスではなくオブジェクト同士が直接つながります。

子オブジェクトが親のプロパティやメソッドを自動で引き継ぎ、探して使います。

プロトタイプチェーンのサンプル

<script>
const Color1 = function() {};
Color1.prototype = {
  getName1() {
    return "red";
  },
};

const Color2 = function() {};

// 継承(プロトタイプチェーンの構築)
Color2.prototype = Object.create(Color1.prototype);
Color2.prototype.constructor = Color2; // constructorを修正(お約束)

Color2.prototype.getName2 = function() {
  return "blue";
};

const c2 = new Color2();
console.log(c2.getName2()); // blue
console.log(c2.getName1()); // red
</script>

解説

const Color1 = function() {};

空のコンストラクタ関数です。
この関数を使ってインスタンスを作るときの「設計図」となります。

 

Color1.prototype = {
  getName1() {
    return "red";
  },
};

Color1のprototypeにgetName1()メソッドを定義しています。
new Color1()で作られたオブジェクトはgetName1()を使えるようになります。

 

const Color2 = function() {};

こちらも空のコンストラクタ関数です。
これを「Color1を継承した子クラス」にします。

 

Color2.prototype = Object.create(Color1.prototype);

ここが継承の本体です。

Object.create(Color1.prototype) →Color1.prototypeを親に持つ空のオブジェクトを作ります。

それをColor2.prototypeに代入することで、 Color2のインスタンスはColor1.prototypeのメソッドを参照できるようになります。

結果として、プロトタイプチェーンは以下のようにつながります:
c2 → Color2.prototype → Color1.prototype → Object.prototype → null

 

Color2.prototype.constructor = Color2;

継承設定で constructor が壊れたので修正しています。

Object.create() によって Color2.prototype.constructor が一時的に Color1 を指してしまうため、 正しく Color2 に戻しています。

 

Color2.prototype.getName2 = function() {
  return "blue";
};

子クラス独自のメソッドを追加しています。

これで Color2 のインスタンスは getName2() を使えるようになります。

 

const c2 = new Color2();

新しいインスタンス c2 を作成しています。

c2.__proto__ === Color2.prototype となります。

 

console.log(c2.getName2()); // blue
console.log(c2.getName1()); // red

getName2()は、Color2.prototypeにあるので直接呼び出せます。

getName1()は、Color2.prototypeにはないので、JavaScriptは上の階層(Color1.prototype)を探索して見つけます。=プロトタイプチェーンの効果です。

 

まとめ図

c2
 └─→ Color2.prototype
        ├─ getName2() → "blue"
        └─→ Color1.prototype
                ├─ getName1() → "red"
                └─→ Object.prototype

関連の記事

JavaScript オブジェクトが存在するか確認
JavaScript prototypeでメソッドを追加する
JavaScript オブジェクト(連想配列)の使い方

△上に戻る