Javascript

MDNで学ぶプロトタイプと継承―ES5・ES6実装徹底解説

ⓘ本ページはプロモーションが含まれています

もっとスキルを活かしたいエンジニアへ

スポンサードリンク
働き方から選べる

無料で使えて良質な案件の情報収集ができるサービス

エンジニアの世界では、「いつでも動ける状態を作っておけ」とよく言われます。
技術やポートフォリオがあっても、自分に合う案件情報を日常的に見れていないと、いざ動こうと思った時に比較や判断が難しくなってしまいます。
普段から案件情報が集まる環境を作っておくと、良い案件が出た時にすぐ動きやすくなりますよ。
筆者自身も、メガベンチャー勤務時代に年収1,500万円を超えた経験があります。振り返ると、技術だけでなく「どんな案件や働き方があるか」を日頃から見ていたことが、キャリアの選択肢を広げるきっかけになりました。
このブログを読んでくれた方に感謝を込めて、実際に使っている情報収集サービスを紹介します。

フルリモート・週3日・高単価、どんな条件も妥協したくないなら

フリーランスボードに無料会員登録する

利用者10万人以上。業界最大規模45万件の案件。AIマッチ機能や無料の相場情報が人気。

年収800万円以上のキャリアアップ・ハイクラス正社員を視野に入れているなら

Beyond Careerに無料相談する

内定獲得率90%以上。紹介先企業とは役員クラスのコネクションがある安心と信頼できるエージェント。


スポンサードリンク

プロトタイプとプロトタイプチェーンの基本概念

JavaScript の継承は「オブジェクトが別のオブジェクトを参照して機能を取得する」仕組みです。このセクションでは、MDN が定義した プロトタイププロトタイプチェーン の概要を整理し、実務でコードを書く前に押さえておくべきポイントを解説します。概念を正しく理解すれば、意図しない継承やバグの原因特定が格段に楽になります。

プロトタイプとは何か

プロトタイプは、各オブジェクトが内部的に保持している [[Prototype]] 参照(別名 proto)です。MDN の「継承とプロトタイプチェーン」によると、オブジェクトがプロパティを検索するときはまず自身を調べ、見つからなければ [[Prototype]] が指すオブジェクトに委譲します。

  • [[Prototype]] はエンジン内部のリンクであり、直接書き換えることはできません。
  • 代替手段として Object.getPrototypeOf()MDN リファレンス)やデバッグ目的の __proto__ アクセサ(MDN の説明)が利用できます。

ポイント:プロトタイプは「オブジェクトのテンプレート」であり、インスタンス自身が保持しない共有ロジックやデフォルトメソッドを格納します。

プロトタイプチェーンの探索アルゴリズム

あるオブジェクト obj がプロパティ p を取得しようとしたとき、エンジンは次の順序で検索を行います。以下の手順は MDN の「プロパティの探索」でも同様に説明されています。

  1. obj 自身に p が存在するか確認
  2. 存在しなければ Object.getPrototypeOf(obj)(=obj.[[Prototype]])へ移動して再チェック
  3. さらに上位のプロトタイプをたどり、null に到達するまで繰り返す

この連鎖が プロトタイプチェーン と呼ばれます。検索が null に至った時点で「プロパティは存在しない」ことが確定します。

ポイント:チェーンの途中で同名プロパティが見つかれば、下位オブジェクト側のものは「隠蔽」されます。デバッグ時にどこで隠蔽されたかを追うことがバグ解決の鍵です。


ES5 での継承パターン:コンストラクタ関数と Object.create

実務コードではまだ ES5 スタイルが残っているケースも多く、コンストラクタ関数Object.create を組み合わせた継承手順を把握しておくことは重要です。このセクションでは、ES5 で安全に継承を実装する方法と注意点を具体例とともに示します。

コンストラクタ関数と prototype の設定方法

まずはベースとなるコンストラクタ関数とその prototype にメソッドを定義する基本形です。以下のコードは MDN の「関数としてのクラス」に相当します。

  • new Vehicle('car') が呼び出されると、エンジンは自動的に新しいオブジェクトを生成し、その [[Prototype]]Vehicle.prototype に設定します。
  • 重要:メソッドはすべて Vehicle.prototype 上に置くことで、インスタンスごとの重複定義を防げます。

Object.create を用いた安全な継承実装例

次に子コンストラクタ CarVehicle からプロパティとメソッドを受け継ぐ例です。Object.create は「空のオブジェクトを作り、指定したオブジェクトを prototype に設定」する安全な手段として MDN でも推奨されています(MDN の Object.create)。

ポイント解説

  • Object.create(Vehicle.prototype) により Car.prototype が生成され、内部的に [[Prototype]]Vehicle.prototype へリンクします。
  • 継承後は Car.prototype.constructor がデフォルトで Vehicle を指すため、必ず手動で Car に戻さなければ instanceof Car の判定が正しく行われません。
  • 完成した継承チェーンは carInstance → Car.prototype → Vehicle.prototype → Object.prototype → null となります。

ES6+ の class 構文と内部的プロトタイプリンク

ES2015(ES6)以降、class 文法が導入され継承記述が大幅に簡略化されました。しかし内部では依然として プロトタイプチェーン が使われている点を理解すれば、旧コードとの比較やトラブルシュートが容易になります。この章では classextends の実装詳細と、MDN が提供する公式解説(クラスの継承)を踏まえて説明します。

class 文の基本形と自動生成される prototype

  • class は実体として 関数オブジェクト が生成され、Vehicle.prototype にメソッドが自動的に登録されます。
  • new Vehicle('bike') の結果得られるインスタンスは内部で [[Prototype]] === Vehicle.prototype を保持します(ES5 と同様の挙動)。

extends が行う二重のプロトタイプ設定

extends が内部で実行している処理は、概念的には次の ES5 ヘルパー関数と同等です(MDN の内部実装例を参考)。

  • インスタンス側Car.prototype.[[Prototype]] → Vehicle.prototype が作られ、new Car() の結果は [[Prototype]]Car.prototype に向く。
  • コンストラクタ側Car.[[Prototype]] → Vehicle が設定され、static メンバーや instanceof 判定に影響します。

実務で役立つサンプル:Vehicle / Car と Animal / Dog

実際のプロジェクトでは「ベースクラス+派生クラス」のパターンが頻出します。ここでは ES5 と ES6 の両方で Vehicle → Car、さらに別例として Animal → Dog を示し、オーバーライドやシャドウイングの注意点を併せて解説します。

ES5 版の完全実装例

ES6 版の完全実装例

オーバーライドとシャドウイングの注意点

  • オーバーライドsuper.method()(ES6)または Parent.prototype.method.call(this, …)(ES5)で親実装を呼び出すことで、コード重複を防ぎつつ機能拡張が可能です。
  • シャドウイングはインスタンス側に同名プロパティがあると、prototype 上の値が「隠蔽」されます。以下は典型的な例です。

ポイント:シャドウイングは意図的に使用すれば便利ですが、デバッグ時に「どこで上書きされたか」を見失いやすいので、プロパティ名は一意に保つか、コメントで明示しておくと安全です。


典型的な落とし穴とデバッグテクニック

実務で遭遇しやすいバグのパターンと、Chrome DevTools を活用したプロトタイプチェーンの可視化手順をまとめました。以下の対策を習慣化すれば、予期せぬ挙動に迅速に対応できます。

共有参照型プロパティによるバグ

回避策はコンストラクタ内部で毎回新しいオブジェクトを作ることです。

ES6 のクラスでも同様に書けます。

constructor プロパティの修正忘れ

Object.create で継承した直後、prototype.constructor が親コンストラクタを指したままだと instanceof 判定が狂います。

ES6 の class は自動で修正されますが、手作業で prototype を操作した場合は必ず確認してください。

Chrome DevTools でプロトタイプチェーンを可視化する方法

  1. コンソールでオブジェクトを出力
    js
    console.dir(carInstance);

    → オブジェクトのツリーが展開でき、[[Prototype]] が最上位に表示されます。

  2. Object.getPrototypeOf を直接呼び出す
    js
    console.log(Object.getPrototypeOf(carInstance));

    これで現在のプロトタイプオブジェクトがコンソールに表示され、チェーンを手動でたどれます。

  3. DevTools の「[[Prototype]]」ビュー

  4. コンソールで変数(例: $0)を選択し、右側ペインの「プロトタイプ」タブを開く。
  5. [[Prototype]] をクリックすると、その上位オブジェクトが展開され、最終的に null まで辿れます。

  6. ショートカット: $0.__proto__ と入力すれば、現在選択中の要素のプロトタイプを即座に取得できます。

ポイント:デバッグ時は「どこまで継承されているか」を視覚的に把握することが、共有参照型やオーバーライドミスの早期発見につながります。


まとめと次のアクション

  • プロトタイプはオブジェクト間でロジックを共有する基盤であり、[[Prototype]]__proto__ の違いを正しく認識しましょう。
  • ES5ではコンストラクタ関数と Object.create を組み合わせ、prototype.constructor の修正を忘れないことが継承の基本です。
  • ES6+class extends は内部的に同じプロトタイプリンクを生成しますが、等価な ES5 コードイメージを持つとデバッグが楽になります。
  • 実務例(Vehicle → Car / Animal → Dog)はオーバーライドとシャドウイングの挙動確認に最適です。自プロジェクトのモデルに合わせて書き換えてみましょう。
  • 典型的な落とし穴(共有参照型プロパティ、constructor 修正忘れ)はコンストラクタ内で初期化し、チェーン全体を DevTools で可視化する習慣で防げます。

次のステップ

  1. 本稿のコードを ブラウザのコンソールまたは CodePen に貼り付けて動作確認。
  2. 自分のドメインモデル(例: User → AdminShape → Rectangle)で同様の継承構造を実装し、プロトタイプチェーンが期待通りに機能するか検証。
  3. デバッグ時は必ず Object.getPrototypeOfDevTools のプロトタイプビュー を併用し、チェーンの各段階を目視で確認する習慣をつける。

これらを実践すれば、プロトタイプ継承に関する理解が確固たるものとなり、コードの保守性とバグ耐性が格段に向上します。 Happy coding!

スポンサードリンク

もっとスキルを活かしたいエンジニアへ

スポンサードリンク
働き方から選べる

無料で使えて良質な案件の情報収集ができるサービス

エンジニアの世界では、「いつでも動ける状態を作っておけ」とよく言われます。
技術やポートフォリオがあっても、自分に合う案件情報を日常的に見れていないと、いざ動こうと思った時に比較や判断が難しくなってしまいます。
普段から案件情報が集まる環境を作っておくと、良い案件が出た時にすぐ動きやすくなりますよ。
筆者自身も、メガベンチャー勤務時代に年収1,500万円を超えた経験があります。振り返ると、技術だけでなく「どんな案件や働き方があるか」を日頃から見ていたことが、キャリアの選択肢を広げるきっかけになりました。
このブログを読んでくれた方に感謝を込めて、実際に使っている情報収集サービスを紹介します。

フルリモート・週3日・高単価、どんな条件も妥協したくないなら

フリーランスボードに無料会員登録する

利用者10万人以上。業界最大規模45万件の案件。AIマッチ機能や無料の相場情報が人気。

年収800万円以上のキャリアアップ・ハイクラス正社員を視野に入れているなら

Beyond Careerに無料相談する

内定獲得率90%以上。紹介先企業とは役員クラスのコネクションがある安心と信頼できるエージェント。


-Javascript