概要: このチュートリアルでは、ES5でJavaScriptのコンストラクタ/プロトタイプパターンを使用してカスタムタイプを定義する方法を学習します。
JavaScriptコンストラクタ/プロトタイプパターンの概要
コンストラクタとプロトタイプパターンを組み合わせることは、ES5でカスタムタイプを定義する最も一般的な方法です。このパターンでは
- コンストラクタパターンはオブジェクトのプロパティを定義します。
- プロトタイプパターンはオブジェクトのメソッドを定義します。
このパターンを使用することにより、カスタムタイプのすべてのオブジェクトは、プロトタイプで定義されたメソッドを共有します。また、各オブジェクトは独自のプロパティを持ちます。
このコンストラクタ/プロトタイプパターンは、コンストラクタパターンとプロトタイプパターンの両方の利点を活用しています。
JavaScriptコンストラクタ/プロトタイプの例
Person
というカスタムタイプを定義したいとします。このタイプには
firstName
とlastName
の2つのプロパティがあります。getFullName()
というメソッドが1つあります。
まず、コンストラクタ関数を使用してプロパティを初期化します。
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
Code language: JavaScript (javascript)
JavaScriptエンジンは、内部で円形で示されるPerson
関数と、四角形で示される匿名オブジェクトを定義します。
Person
関数には、匿名オブジェクトを参照するprototype
プロパティがあります。匿名オブジェクトには、Person
関数を参照するconstructor
プロパティがあります。
次に、Person
関数のprototype
オブジェクトにgetFullName()
メソッドを定義します。
Person.prototype.getFullName = function () {
return this.firstName + ' ' + this.lastName;
};
Code language: JavaScript (javascript)
JavaScriptは、Person.prototype
オブジェクトにgetFullName()
メソッドを次のように定義します。
3番目に、Person
タイプの複数のインスタンスを作成します。
let p1 = new Person("John", "Doe");
let p2 = new Person("Jane", "Doe");
console.log(p1.getFullName());
console.log(p2.getFullName());
Code language: JavaScript (javascript)
出力
'John Doe'
'Jane Doe'
Code language: JavaScript (javascript)
JavaScriptは、p1
とp2
の2つのオブジェクトを作成します。これらのオブジェクトは、[[Prototype]]
リンケージを介してPerson.prototype
オブジェクトにリンクされます。
各オブジェクトには、独自のfirstName
およびlastName
プロパティがあります。ただし、同じgetFullName()
メソッドを共有します。
p1
またはp2
オブジェクトでgetFullName()
メソッドを呼び出すと、JavaScriptエンジンはこれらのオブジェクトでメソッドを検索します。JavaScriptエンジンはそこでメソッドを見つけられないため、プロトタイプリンケージをたどり、Person.prototype
オブジェクトでメソッドを検索します。
Person.prototype
オブジェクトにはgetFullName()
メソッドがあるため、JavaScriptは検索を停止し、メソッドを実行します。
すべてをまとめる
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
Person.prototype.getFullName = function () {
return this.firstName + ' ' + this.lastName;
};
let p1 = new Person('John', 'Doe');
let p2 = new Person('Jane', 'Doe');
console.log(p1.getFullName());
console.log(p2.getFullName());
Code language: JavaScript (javascript)
ES6のクラス
ES6では、コンストラクタ/プロトタイプパターンを使いやすくするclassキーワードが導入されました。たとえば、以下では、class
キーワードを使用して同じPerson
タイプを定義しています。
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
getFullName() {
return this.firstName + " " + this.lastName;
}
}
let p1 = new Person('John', 'Doe');
let p2 = new Person('Jane', 'Doe');
console.log(p1.getFullName());
console.log(p2.getFullName());
Code language: JavaScript (javascript)
この構文では、class
はプロパティの初期化をconstructor
メソッドに移動します。また、getFullName()
メソッドをconstructor
関数と同じ場所にまとめます。
クラス構文は、よりクリーンで簡潔に見えます。ただし、これはコンストラクタ/プロトタイプパターンにいくつかの機能強化を加えた糖衣構文です。
クラスの詳細については、JavaScriptクラスのチュートリアルをご覧ください。
まとめ
- ES5でカスタムタイプを定義するには、JavaScriptのコンストラクタ/プロトタイプを使用します。
- コンストラクタ関数でオブジェクトのプロパティを初期化し、すべてのインスタンスで共有できるメソッドとプロパティをプロトタイプオブジェクトで定義します。