Static Members

The class Point that we started with in Section 3
was of course not fully representative of a class in a traditional OO language. One thing that
was missing were static members (fields and methods). Let us assume that we want to instrument our code with
counters that tell us how many times each of the two methods was called. Moreover,
we want a way to reset all counters to zero. This is what the class Point would
now look like:

The access via the constructor, as in the first line of code above, is of course
the preferred way of accessing a static field. But the access via an object works
as well, due to property lookup in the prototype.

So what about static methods? They are
characterized by these properties:

They have access to static fields, but not to non-static ones.

They are accessible via the class name, in the absence of any instantiations.

Apart from a certain lack of enforcement, which we'll discuss in a moment, this can
again be achieved by putting them in the prototype:

Since all fields are public in JavaScript, we don't need the
getters for the counters. Some people would add them as a matter of style.

I mentioned earlier that JavaScript's way of modeling static methods lacks
enforcement. Indeed, when you look at the static and non-static methods in the
Point example, you see that they just sit there side by side in the prototype
object. The only thing that distinguishes them from each other is the fact that static methods,
via programming discipline, do not access non-static fields. There is nothing
that prevents us from calling a non-static method as if it were static, as in

// Bad: non-static method called as if it were static
var label = Point.prototype.getLabel();

This doesn't make sense because the receiver of the function call is Point.prototype.
Therefore, the properties x and y that are referenced in the body of
getLabel will be undefined, unless, of course, somebody has added properties named
x and y to the global object, which would be even worse. Similarly,
nothing prevents somebody from altering a static method and make it access non-static fields,
thereby effectively turning it into a non-static method. Existing calls to that
function through an object would continue to work just fine, while calls via the
constructor would become non-sensical.

Examples of this kind of laxness abound in JavaScript. As a matter of fact, we've seen
another one earlier in Section 4: constructor functions
can be called in a manner that results in non-sensical behavior. If this
kind of thing really bothers you, JavaScript is not for you. Personally, I'm a bit
on the fence in this regard. I do miss the kind of enforcement that traditional OO
languages like Java afford. On the other hand, experience shows that in the long
run, enforcement of design principles, no matter how reasonable they are, contributes
surprisingly little to software quality.