プロトタイプチェーンとは?
JavaScriptでは、オブジェクトは他のオブジェクトを継承する仕組みを持っており、この仕組みがプロトタイプチェーンと呼ばれます。プロトタイプチェーンにより、オブジェクトは自分のプロパティやメソッドだけでなく、継承されたプロトタイプオブジェクトのプロパティやメソッドにもアクセスできます。
プロトタイプチェーンの基本構造
すべてのJavaScriptオブジェクトには、__proto__(プロトタイプオブジェクト)という特別なプロパティがあります。このプロパティはオブジェクトのプロトタイプを指し、オブジェクトが持っていないプロパティやメソッドを、プロトタイプから取得できるようにします。
プロトタイプチェーンの例
function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
console.log("Hello, my name is " + this.name);
};
const person1 = new Person("Taro");
person1.greet(); // "Hello, my name is Taro"
この例では、person1オブジェクトにはgreetメソッドが直接定義されていません。しかし、person1はPerson.prototypeにリンクされているため、greetメソッドをプロトタイプチェーンを通じて使用できます。
プロトタイプの継承
オブジェクトを生成すると、そのオブジェクトはコンストラクタ関数のプロトタイプからプロパティやメソッドを継承します。これにより、すべてのオブジェクトは親となるオブジェクトの機能を利用できます。JavaScriptでは、標準的な組み込みオブジェクトであるObjectもまたプロトタイプチェーンの一部です。
Objectプロトタイプからの継承
const obj = { name: "Hanako" };
// オブジェクトには直接toStringメソッドがないが、プロトタイプチェーンを通じて利用できる
console.log(obj.toString()); // "[object Object]"
この例では、objオブジェクトはtoStringメソッドを直接持っていませんが、Objectのプロトタイプチェーンを通じてtoStringを呼び出すことができます。すべてのオブジェクトはObject.prototypeからこのメソッドを継承しています。
プロトタイプチェーンの探索
JavaScriptでは、オブジェクトに対してプロパティやメソッドを呼び出すと、まずそのオブジェクト自身のプロパティが検索されます。もしそのプロパティが見つからなければ、プロトタイプチェーンをたどって親オブジェクトにそのプロパティを探しに行きます。プロトタイプチェーンを通じてもプロパティが見つからない場合、undefinedが返されます。
プロトタイプチェーンの探索例
const animal = {
eat: function() {
console.log("Eating");
}
};
const dog = Object.create(animal);
dog.bark = function() {
console.log("Barking");
};
dog.bark(); // "Barking"(dogに直接定義されているメソッド)
dog.eat(); // "Eating"(プロトタイプチェーンを通じてanimalから継承されたメソッド)
この例では、dogオブジェクトはanimalオブジェクトをプロトタイプとして持ち、dogには直接定義されていないeatメソッドが、プロトタイプチェーンを通じて利用されています。
プロトタイプチェーンとhasOwnProperty
オブジェクトが持つhasOwnPropertyメソッドを使うと、そのオブジェクトが直接所有しているプロパティのみを判定することができます。プロトタイプチェーンにあるプロパティは判定対象に含まれません。
hasOwnPropertyの例
const person = {
name: "Taro"
};
console.log(person.hasOwnProperty("name")); // true
console.log(person.hasOwnProperty("toString")); // false(toStringはプロトタイプチェーン上にある)
この例では、nameプロパティはpersonオブジェクト自身が持っているためtrueが返されますが、toStringメソッドはObject.prototypeから継承されているため、hasOwnPropertyではfalseが返されます。
プロトタイプチェーンの操作
プロトタイプチェーンを操作するためには、Object.create()を使用して特定のオブジェクトをプロトタイプとして持つ新しいオブジェクトを作成するか、__proto__を直接操作します。ただし、__proto__を直接操作するのはパフォーマンス上の理由から推奨されません。
Object.createを使ったプロトタイプチェーンの例
const parentObj = {
greet: function() {
console.log("Hello from parent");
}
};
const childObj = Object.create(parentObj);
childObj.sayHi = function() {
console.log("Hi from child");
};
childObj.greet(); // "Hello from parent"(親オブジェクトから継承)
childObj.sayHi(); // "Hi from child"(自分自身のメソッド)
この例では、parentObjをプロトタイプとするchildObjオブジェクトを作成し、プロトタイプチェーンを通じて親オブジェクトのメソッドにアクセスしています。
まとめ
JavaScriptにおけるプロトタイプチェーンは、オブジェクト指向プログラミングの中心的な概念です。オブジェクトはプロトタイプチェーンを通じて他のオブジェクトのプロパティやメソッドを継承し、効率的にコードを再利用することができます。プロトタイプチェーンの理解が深まることで、JavaScriptのオブジェクト指向プログラミングの基礎がより明確になります。