プロトタイプの探索順序とは?
JavaScriptでは、オブジェクトが自身のプロパティやメソッドを持っていない場合、プロトタイプチェーンを通じて上位のオブジェクトからプロパティやメソッドを探します。このプロセスがプロトタイプの探索順序です。オブジェクトが自身のプロパティやメソッドを持たない場合、JavaScriptは自動的にそのオブジェクトのプロトタイプを参照し、該当のプロパティを見つけるまで上位のプロトタイプを順に探索します。
プロトタイプの探索順序の基本
プロトタイプの探索順序は次のように行われます。
- オブジェクト自身のプロパティ: まず、オブジェクトが自身にプロパティやメソッドを持っているかを確認します。
- プロトタイプオブジェクト: 自身に該当のプロパティが見つからない場合、オブジェクトの
__proto__
(プロトタイプオブジェクト)を探索します。 - プロトタイプチェーンの探索: さらに上位のプロトタイプを順に参照し、該当のプロパティが見つかるか、チェーンの終端(
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は次の手順で探索を行います。
- オブジェクト自身に該当するプロパティやメソッドがあるか確認する。
- オブジェクトのプロトタイプ(
__proto__
)を探索する。 - プロトタイプチェーンを辿り、さらに上位のプロトタイプを探索する。
- 最終的に、該当するプロパティが見つからなければ、
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
この例では、ElectricCar
がCar
を継承しており、プロトタイプチェーンを通じてstart
メソッドを利用しています。同時に、ElectricCar
クラス独自のcharge
メソッドも追加されています。
まとめ
プロトタイプの探索順序は、JavaScriptにおけるオブジェクトの継承とプロパティの検索において重要な役割を果たします。プロトタイプチェーンは、オブジェクト自体が持たないプロパティやメソッドを上位のプロトタイプから探し出す仕組みです。hasOwnProperty
メソッドを利用することで、プロトタイプチェーンの探索を制御することも可能です。
プロトタイプチェーンの理解を深めることで、JavaScriptのオブジェクト指向プログラミングをより効果的に活用できるようになります。