Declaring prototype properties is not an anti-pattern at all. When I look at the prototype object, I think: "this is what a prototype object of this type has for data and methods."
Others warn of the absence of reference value properties in the prototype, for example: Foo.prototype.bar = []; --- because arrays and objects are reference types. The type of reference is immutable, so each instance of a “class” refers to the same array or object. Just set them to null in the prototype, then give them a value in the constructor.
I always include all the properties in the prototype for one very understandable reason: communication with other programmers, which properties are publicly available and what are their default values, without having to sift them through the constructor in order to understand this.
This becomes especially useful if you are creating a shared library that requires documentation.
Consider the following example:
function Point(x, y) { this.x = x; this.y = y; } Point.prototype = { constructor: Point, isAbove: function(other) { return this.y > other.y; } };
(Documentation format: PDoc )
Just reading the documentation is a little awkward because information about the x and y properties is built into the constructor function. Compare this to the “anti-pattern" of incorporating these properties into the prototype:
function Point(x, y) { this.x = x; this.y = y; } Point.prototype = { x: 0, y: 0, constructor: Point, isAbove: function(other) { return this.y > other.y; } };
Now, looking at the prototype, you get a snapshot of a real object, which is much easier to visualize in your head, and easier for the author to write documentation. The constructor function is also not cluttered with documentation and is not related to animating a Point object.
A prototype has everything and is a canonical source of information about what a "prototype" Point object has for both methods and data.
I would say that not including the data properties in the prototype is an anti-pattern.