プロトタイプでプロパティを宣言することは、アンチパターンではありません。オブジェクトを見ると、prototype
「これが、このタイプの典型的なオブジェクトがデータとメソッドに対して持っているものです」と思います。
他の人は、プロトタイプでプロパティに参照値を与えることに対して警告しています。たとえばFoo.prototype.bar = [];
、配列とオブジェクトは参照型であるためです。参照型は不変であるため、「クラス」のすべてのインスタンスは同じ配列またはオブジェクトを参照します。null
それらをプロトタイプで設定し、コンストラクターで値を指定するだけです。
非常に明確な理由の1つとして、常にすべてのプロパティをプロトタイプに含めます。他のプログラマーに、コンストラクターを調べて把握することなく、公開されているプロパティとそのデフォルト値を伝えることです。
これは、ドキュメントが必要な共有ライブラリを作成する場合に特に役立ちます。
この例を考えてみましょう。
/**
* class Point
*
* A simple X-Y coordinate class
*
* new Point(x, y)
* - x (Number): X coordinate
* - y (Number): Y coordinate
*
* Creates a new Point object
**/
function Point(x, y) {
/**
* Point#x -> Number
*
* The X or horizontal coordinate
**/
this.x = x;
/**
* Point#y -> Number
*
* The Y or vertical coordinate
**/
this.y = y;
}
Point.prototype = {
constructor: Point,
/**
* Point#isAbove(other) -> bool
* - other (Point): The point to compare this to
*
* Checks to see if this point is above another
**/
isAbove: function(other) {
return this.y > other.y;
}
};
(ドキュメント形式:PDoc)
x
およびy
プロパティに関する情報がコンストラクター関数内に埋め込まれているため、ここではドキュメントを読むだけでは少し厄介です。これらのプロパティをプロトタイプに含める「アンチパターン」とは対照的です。
/**
* class Point
*
* A simple X-Y coordinate class
*
* new Point(x, y)
* - x (Number): X coordinate
* - y (Number): Y coordinate
*
* Creates a new Point object
**/
function Point(x, y) {
this.x = x;
this.y = y;
}
Point.prototype = {
/**
* Point#x -> Number
*
* The X or horizontal coordinate
**/
x: 0,
/**
* Point#y -> Number
*
* The Y or vertical coordinate
**/
y: 0,
constructor: Point,
/**
* Point#isAbove(other) -> bool
* - other (Point): The point to compare this to
*
* Checks to see if this point is above another
**/
isAbove: function(other) {
return this.y > other.y;
}
};
ここでプロトタイプを見ると、実際のオブジェクトのスナップショットが得られます。これは、頭の中で視覚化するのがはるかに簡単で、作成者がドキュメントを作成するのも簡単です。Point
コンストラクター関数もドキュメントで雑然としておらず、オブジェクトに命を吹き込むというビジネスに固執しています。
プロトタイプにはすべてが含まれており、メソッドとデータの両方について「プロトタイプ」Point
オブジェクトが持つものに関する標準的な情報源です。
プロトタイプにデータプロパティを含めないことがアンチパターンであると私は主張します。