Javascript

JavaScript プロトタイプ継承の実装例とベストプラクティス

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

スポンサードリンク

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

オブジェクトは内部スロット [[Prototype]](ES2022 では prototype)に別のオブジェクトへの参照を持ちます。この参照をたどってプロパティ検索が行われる仕組みを プロトタイプチェーン と呼びます。

  • 最上位は null を指すオブジェクトで、ここまで到達すると検索は終了します。
  • 実装例: dog.__proto__ → animal.__proto__ → Object.prototype.__proto__ → null

MDN の解説(Prototype chain and inheritance)や ECMA‑262 仕様(#sec-ordinary-object-internal-methods-and-internal-slots-prototype)を参照すると、内部的に「[[Get]]」アルゴリズムが再帰的に呼び出されることが分かります。

dog.bark() が見つからない場合、エンジンは自動的に animal を検索し、最終的に Object.prototype まで遡ります。


2. [[Prototype]]__proto__ の違い

項目 説明
[[Prototype]] 仕様上の内部スロットで、直接操作できません。ECMAScript のオブジェクトは必ずこのスロットを持ちます(§9.1.2)。
__proto__ デバッグや非標準的操作のためにブラウザが実装したアクセサです。MDN では「非推奨」ではなく「互換性のためだけに残っている」旨が記載されています(Object.prototype.proto)。
正式な取得・設定手段 Object.getPrototypeOf(obj) / Object.setPrototypeOf(obj, proto) が標準です。

実務上の指針
- 参照は Object.getPrototypeOfObject.setPrototypeOf を使う。
- obj.__proto__ はコンソールでの確認以外では使用しない。


3. Function コンストラクタで安全に継承する

3.1 基本パターン(Animal → Dog)

ポイントは Object.create(Animal.prototype) により、親コンストラクタの副作用を排除しつつプロトタイプだけを継承できる点です。

3.2 共有参照型プロパティが招くバグと回避策

回避策は、参照型(配列・オブジェクト)をコンストラクタ内部で生成することです。

ベストプラクティス
- prototype にはメソッドだけを置く。
- 参照型は必ずコンストラクタで初期化する。


4. Object.create を活用した継承パターン

4.1 Object.create の利点

  • 副作用がない:親コンストラクタを呼び出さずにプロトタイプチェーンだけを構築。
  • メモリ効率が高い:不要なインスタンスフィールドが作られません。
  • 可読性が向上:継承関係が一目で分かります。

MDN の解説(Object.create())でも「純粋なプロトタイプオブジェクトを生成」する手段として推奨されています。

4.2 実装例(Animal → Cat)

チェーンの可視化


5. ES6 class 構文と内部的なプロトタイプ継承

5.1 class が行う処理

ES2022 の仕様(#sec-class-definitions)によれば、次のように変換されます。

は概念的に以下と同等です。

class は構文糖衣であり、内部では Object.createObject.setPrototypeOf が実行されます。

5.2 super() の正しい使い方

  • super() はコンストラクタの最初に呼び出す(それ以前に this を参照すると ReferenceError)。
  • 親クラスでインスタンス固有の配列などを初期化する場合は、super() 後に子側で追加プロパティを設定します。


6. デバッグ手法と継承スタイル選択基準

6.1 プロトタイプチェーンを確認する方法

Object.getPrototypeOf は標準 API(MDN: Object.getPrototypeOf)であり、__proto__ より安全です。

6.2 継承スタイルの比較表

スタイル 実行速度 メモリ使用量 デバッグ容易性 推奨度
Function + Object.create
ES6 class 高(エンジン最適化)
prototype = new Parent() 低(副作用あり)

結論
- ES6+ が利用可能なプロジェクトclass を採用すれば可読性と保守性が向上します。
- レガシー環境や細かい prototype 操作が必要な場合は、Object.create と関数コンストラクタの組み合わせが安全です。


まとめ(約230文字)

  • プロトタイプチェーンは [[Prototype]] の連鎖で属性検索を行い、正式取得は Object.getPrototypeOf
  • Function コンストラクタでも Object.createParent.call(this) を組み合わせれば副作用のない継承が実現できる。
  • Object.create は余計なコンストラクタ実行を防ぎ、メモリ効率が高いため推奨される手法である。
  • ES6 class は内部的に同様の prototype 継承をラップし、可読性・保守性から主流になる。
  • デバッグは console.dirObject.getPrototypeOf を併用し、プロジェクト要件と環境に応じて継承スタイルを選択することがベストプラクティスである。
スポンサードリンク

-Javascript