Recall that our next order of business is to find out how to deal with methods (member functions)
in pre-ECMAScript-6 JavaScript. Perhaps the best way to understand this is to first look at how not to do it.
Given the constructor function as shown in the previous section,
you may be tempted to provide methods such as distance (see the
Point class example in Section 3) by adding them to the constructor:
// Bad constructor function function Point(x, y) { this.x = x; this.y = y; // No! Don't do this! this.distance = function(other) { return Math.sqrt(Math.pow(this.x - other.x, 2) + Math.pow(this.y - other.y, 2)); }; }This “solution” will work deceptively well: var p1 = new Point(0.0, 0.0); var p2 = new Point(3.0, 4.0); var dist = p2.distance(p1); // dist is 5.0The problem, of course, is that this is a double whammy of wastefulness and inefficiency. Firstly, a new copy of the function distance is created for every Point object.
So at any given time, your JavaScript program will hold as many copies of the function
distance as it has Point instantiations. Secondly, every
Point object now has one more property, which, depending on implementation,
runtime optimization, and circumstances, may or may not cause additional overhead.
What we really want is a single place where we can put one copy each of the methods
And that's exactly how pre-ECMAScript-6 JavaScript does it. All that remains to be said is where that
magical single place is. First, you need to recall that in JavaScript, every object has
a property lookup chain consisting of linked objects called prototypes.
When a piece of code tries to access a property of an object, as in
By default, an object's property lookup chain consists of a single prototype, namely,
var p = new Point(0.0, 0.0);an additional prototype object is inserted at the beginning of the chain. This prototype object
Point methods. The entire setup is illustrated in
Figure 2. Thus, the complete pre-ECMAScript-6 JavaScript
implementation of the Point class of Section 3 is:
// // The equivalent of the Point class in pre-ECMAScript-6 JavaScript // function Point(x, y) { this.x = x; this.y = y; } Point.prototype.distance = function(other) { return Math.sqrt(Math.pow(this.x - other.x, 2) + Math.pow(this.y - other.y, 2)); } Point.prototype.getLabel = function() { return "(" + this.x.toFixed(2) + ", " + this.y.toFixed(2) + ")"; };Notice that when you refer to fields such as x and y
inside a method, you have to qualify them with this , as in
this.x.toFixed(2) in getLabel above. That's easy to
forget as it is optional in traditional class-based languages.
Here's the quintessential use of points again: var p1 = new Point(0.0, 0.0); var p2 = new Point(3.0, 4.0); var dist = p2.distance(p1); // dist is 5.0To reiterate, the property access p2.distance in the third line of this code now works as follows:
First, it is checked if the object p2 has distance as an “own” property.
If that were the case, it would be used. Since p2 does not have such an “own” property,
lookup proceeds to the object Point.prototype . Since a property named distance
is found there, its value is fetched and used as if it were a property of p2 . In particular,
p2 becomes the receiver of the function call p2.distance(p1) , meaning that
inside the function distance , the special variable this is bound to p2 .
For most JavaScript application programmers, this is all there is to know: the prototype that is common
to all A Word on Terminology
As mentioned earlier, JavaScript objects that are created with the Point constructor are
often called Point instances, or instantiations of Point . This is
consistent with the behavior of JavaScript's instanceof operator:
var p = new Point(0.0, 0.0); p instanceof Point; //trueBut what kind of thing is Point ? Technically, it is a constuctor function.
But since there can be instances of it, many in the JavaScript community also call it a class.
That's a bit odd, though, because everybody agrees that JavaScript is classless. It has also been called
a type, or custom type. That's promising because JavaScript has the notion of data types,
such as Number, String, etc. Unfortunately, though, the JavaScript typeof operator
informs us that Point is not a data type:
var p = new Point(0.0, 0.0); typeof p; //returns 'object'The bottom line is that as far as terminology is concerned, I don't know what Point is (or perhaps more precisely, the combination of the constructor function Point
and the prototype Point.prototype ). Some guidance from an authoritative
source would be helpful in this matter.
|