Объявление свойств прототипа вовсе не является антипаттерном. Когда я смотрю на объект prototype
, я думаю: «Это то, что прототипный объект этого типа имеет для данных и методов».
Другие предостерегают от присвоения свойствам ссылочного значения в прототипе, например: Foo.prototype.bar = [];
--- потому что массивы и объекты являются ссылочными типами. Ссылочный тип неизменяем, поэтому каждый экземпляр «класса» относится к одному и тому же массиву или объекту. Просто установите для них значение null
в прототипе, а затем присвойте им значение в конструкторе.
Я всегда включаю все свойства в прототип по одной очень ясной причине: сообщить другим программистам, какие свойства общедоступны и каковы их значения по умолчанию, не требуя от них просеивания через конструктор, чтобы понять это.
Это становится особенно полезным, если вы создаете разделяемую библиотеку, для которой требуется документация.
Рассмотрим этот пример:
/**
* 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
объекта как для методов , так и для данных.
Я бы сказал, что не включение свойств данных в прототип является антишаблоном.
person
Greg Burghardt
schedule
28.10.2014