JavaScriptコンストラクタ/プロトタイプパターン

概要: このチュートリアルでは、ES5でJavaScriptのコンストラクタ/プロトタイプパターンを使用してカスタムタイプを定義する方法を学習します。

JavaScriptコンストラクタ/プロトタイプパターンの概要

コンストラクタプロトタイプパターンを組み合わせることは、ES5でカスタムタイプを定義する最も一般的な方法です。このパターンでは

  • コンストラクタパターンはオブジェクトのプロパティを定義します。
  • プロトタイプパターンはオブジェクトのメソッドを定義します。

このパターンを使用することにより、カスタムタイプのすべてのオブジェクトは、プロトタイプで定義されたメソッドを共有します。また、各オブジェクトは独自のプロパティを持ちます。

このコンストラクタ/プロトタイプパターンは、コンストラクタパターンとプロトタイプパターンの両方の利点を活用しています。

JavaScriptコンストラクタ/プロトタイプの例

Personというカスタムタイプを定義したいとします。このタイプには

  • firstNamelastNameの2つのプロパティがあります。
  • getFullName()というメソッドが1つあります。

まず、コンストラクタ関数を使用してプロパティを初期化します。

function Person(firstName, lastName) {
	this.firstName = firstName;
	this.lastName = lastName;
}Code language: JavaScript (javascript)

JavaScriptエンジンは、内部で円形で示されるPerson関数と、四角形で示される匿名オブジェクトを定義します。

Person関数には、匿名オブジェクトを参照するprototypeプロパティがあります。匿名オブジェクトには、Person関数を参照するconstructorプロパティがあります。

JS prototype- Person prototype

次に、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は、p1p2の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のコンストラクタ/プロトタイプを使用します。
  • コンストラクタ関数でオブジェクトのプロパティを初期化し、すべてのインスタンスで共有できるメソッドとプロパティをプロトタイプオブジェクトで定義します。
このチュートリアルは役に立ちましたか?