カテゴリー
JavaScript

constructorプロパティ

JavaScriptの関数はすべて自動的にprototypeプロパティを持つ。
このプロパティの値は、列挙不可のconstructorプロパティだけを持つオブジェクト。

つまり一般的に、オブジェクトは、コンストラクタを参照するconstructorプロパティを継承する。
コンストラクタによってクラスが同一かどうかを判断するので、オブジェクトのクラスを表すものとして、constructorプロパティが使える。

example 9-2 コンストラクタを使ったRangeクラス

//新しいRangeオブジェクトを初期化するコンストラクタ関数
//オブジェクトを生成したり返したりせず、thisを初期化しているだけ
function Range(from, to) {
	//新しいRangeオブジェクトの始端と終端を保存する
	//この2つのプロパティは継承したものではない。オブジェクトに一意なもの
	this.from = from;
	this.to = to;
}

//全Rangeオブジェクトが、このオブジェクトを継承する
//オブジェクト名は「ptototype」でなければならない
Range.ptototype = {
	//xが範囲内であればtrueを返し、範囲外であればfalseを返す
	//このメソッドは数値だけでなく、文字列やDateオブジェクトでも動作する
	includes: function(x) { return this.from <= x && x <= this.to },

	//範囲中に含まれる各整数に対して、一度ずつfを呼び出す
	//このメソッドは数値に対してしか動作しない
	foreach: function(f) {
		for (var x = Math.ceil(this.from); x < <= this.to; x++) f(x);
	},

	//rangeオブジェクトの文字列表現を返す
	toString: function() { return "(" + this.from + "..." + this.to + ")"}
};

//Rangeオブジェクトの使用例
var r = new Range(1,3);			//新しいRangeオブジェクトを生成
r.includes(2);							//true: 2は範囲内
r.foreach(console.log);			//1 2 3 を出力する
console.log(r);							//(1...3)を出力する

上記の例のRangeクラスでは、もともと定義されていた Range.prototype オブジェクトを、
新たに生成したオブジェクトで上書きしている。
そして、この上書きしたプロトタイプでは、constructorプロパティを設定していない。
したがって、Rangeクラスのインスタンスは、constructorプロパティを持たないことになる。

この問題を解決するには、以下のように明示的にプロトタイプに constructorプロパティを追加する。

Range.ptototype = {
     constructor: Range,     //コンストラクタへの参照を明示的に設定する
     includes: 省略 ,
     foreach: 省略 ,
     toString: 省略 
 };

または、constructorプロパティを持つ定義済みのプロトタイプオブジェクトを使って、
このプロトタイプオブジェクトにメソッドを追加する

// 定義済みの Range.prototype を拡張する
// 自動的に生成される Range.prototype.constructor プロパティを上書きしない。
 Range.ptototype.includes = 省略;
 Range.ptototype.foreach = 省略;
 Range.ptototype.toString = 省略;

参考書籍:

オライリー JavaScript 第6版

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です