プロトタイプの探索順序 | プロトタイプチェーンの理解 | JavaScript 超完全入門 基本から発展までのすべて

スポンサーリンク
スポンサーリンク

プロトタイプの探索順序とは?

JavaScriptでは、オブジェクトが自身のプロパティやメソッドを持っていない場合、プロトタイプチェーンを通じて上位のオブジェクトからプロパティやメソッドを探します。このプロセスがプロトタイプの探索順序です。オブジェクトが自身のプロパティやメソッドを持たない場合、JavaScriptは自動的にそのオブジェクトのプロトタイプを参照し、該当のプロパティを見つけるまで上位のプロトタイプを順に探索します。

プロトタイプの探索順序の基本

プロトタイプの探索順序は次のように行われます。

  1. オブジェクト自身のプロパティ: まず、オブジェクトが自身にプロパティやメソッドを持っているかを確認します。
  2. プロトタイプオブジェクト: 自身に該当のプロパティが見つからない場合、オブジェクトの__proto__(プロトタイプオブジェクト)を探索します。
  3. プロトタイプチェーンの探索: さらに上位のプロトタイプを順に参照し、該当のプロパティが見つかるか、チェーンの終端(null)に達するまで探索を続けます。

探索順序の具体例

以下の例を使って、プロトタイプチェーンの探索順序を確認してみましょう。

プロトタイプチェーンの例

function Animal(name) {
  this.name = name;
}

Animal.prototype.speak = function() {
  return this.name + ' makes a sound.';
}

function Dog(name, breed) {
  Animal.call(this, name);
  this.breed = breed;
}

Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

Dog.prototype.bark = function() {
  return this.name + ' barks.';
}

let myDog = new Dog('Buddy', 'Golden Retriever');

console.log(myDog.bark());  // 出力: Buddy barks.
console.log(myDog.speak()); // 出力: Buddy makes a sound.

このコードでは、DogオブジェクトはAnimalオブジェクトを継承しています。myDogオブジェクトに対してspeakメソッドを呼び出すと、プロトタイプチェーンがAnimal.prototypeまで遡り、そのメソッドが実行されます。一方で、barkメソッドはDog.prototypeに存在するため、探索はDog.prototypeで完了します。

プロトタイプチェーンの仕組み

プロトタイプチェーンを辿る際、JavaScriptは次の手順で探索を行います。

  1. オブジェクト自身に該当するプロパティやメソッドがあるか確認する。
  2. オブジェクトのプロトタイプ(__proto__)を探索する。
  3. プロトタイプチェーンを辿り、さらに上位のプロトタイプを探索する。
  4. 最終的に、該当するプロパティが見つからなければ、nullに到達する。

プロトタイプチェーンの探索範囲の制御

プロトタイプチェーンの探索を制御したい場合、JavaScriptのObject.prototype.hasOwnProperty()メソッドを使用します。このメソッドは、オブジェクト自身が特定のプロパティを持っているかをチェックし、プロトタイプチェーンの探索を避けることができます。

hasOwnPropertyメソッドの使用例

let myDog = new Dog('Buddy', 'Golden Retriever');

console.log(myDog.hasOwnProperty('name'));  // true
console.log(myDog.hasOwnProperty('speak')); // false

この例では、myDogオブジェクトは自身でnameプロパティを持っているため、hasOwnPropertyメソッドはtrueを返します。一方、speakメソッドはプロトタイプチェーン上に存在するため、このメソッドはfalseを返します。

プロトタイプチェーンの活用例

次に、プロトタイプチェーンの活用例を紹介します。この例では、親クラスのメソッドを活用しつつ、子クラスで独自のメソッドを追加します。

プロトタイプの活用例

function Car(make, model) {
  this.make = make;
  this.model = model;
}

Car.prototype.start = function() {
  return this.make + ' ' + this.model + ' starts.';
}

function ElectricCar(make, model, batteryCapacity) {
  Car.call(this, make, model);
  this.batteryCapacity = batteryCapacity;
}

ElectricCar.prototype = Object.create(Car.prototype);
ElectricCar.prototype.constructor = ElectricCar;

ElectricCar.prototype.charge = function() {
  return 'Charging battery: ' + this.batteryCapacity + ' kWh';
}

let myElectricCar = new ElectricCar('Tesla', 'Model S', 100);
console.log(myElectricCar.start());  // 出力: Tesla Model S starts.
console.log(myElectricCar.charge()); // 出力: Charging battery: 100 kWh

この例では、ElectricCarCarを継承しており、プロトタイプチェーンを通じてstartメソッドを利用しています。同時に、ElectricCarクラス独自のchargeメソッドも追加されています。

まとめ

プロトタイプの探索順序は、JavaScriptにおけるオブジェクトの継承とプロパティの検索において重要な役割を果たします。プロトタイプチェーンは、オブジェクト自体が持たないプロパティやメソッドを上位のプロトタイプから探し出す仕組みです。hasOwnPropertyメソッドを利用することで、プロトタイプチェーンの探索を制御することも可能です。

プロトタイプチェーンの理解を深めることで、JavaScriptのオブジェクト指向プログラミングをより効果的に活用できるようになります。