Closures, Javascript, and Objects - Part II

This is the second and briefer post of two on OOP in Javascript. Previously we covered object creation using the notion of closures and implicit object creation with the ‘{}’ syntax. Now we’ll cover more advanced object creation with prototypes and the new keyword.

In the prior post we created objects implicitly within the closure of an outer function. The enclosing function enabled us to initialize the new object and create a runtime en­vi­ron­ment for it. In creating a closure and runtime en­vi­ron­ment the outer function acted as a con­struc­tor of the created object.

The new keyword enables us to create a function that also acts as an object con­struc­tor. A function that creates an object using the new keyword is similar in form to the functions we used in Part I but with fewer lines of code. Here is an example rewritten from the last post to take advantage of new:

var c = function() {
  this.x = 3;
  this.y = 4;
  this.f = function(z) { //map an anonymous function to the name f in the map obj
     return this.x + this.y + z;
  }
  this.f2 = function(z) { //map another anonymous function to the name f2
    return this.x - this.y - z;
  }
}
var myObject = new c();
myObject.f(5) // = 12
myObject.f2(5) // = -6

The function c when used with the new keyword creates an object with the properties x, y, f, and f2. The new keyword’s behavior is very similar to what we got previously from using ‘{}’, but with less code. When the function c runs, ‘this’ refers to the newly created object that will be returned. It is as if we had used ‘{}’ to create an object and then manually assigned properties to it. One key note about con­struc­tor functions though, the function will break if called without the new keyword. When called without the new keyword the function operates normally and not like a con­struc­tor, in particular ‘this’ will no longer refer to a new object, but will likely refer to something in the context of the function. In short, calling the con­struc­tor without the new keyword will have un­pre­dictable and undesired results.

Using the simpler object con­struc­tion syntax we can harness prototypes to make our objects more efficient. Regarding prototypes – Javascript is not a class based object oriented language, instead Javascript is a prototyped based language.. While the prior statement has several im­pli­ca­tions, for now we can focus on the central concept of the prototype.

One way of thinking of prototypes is that they form the basis for an object to be con­struct­ed from. If an object, A’s prototype contains a member B, then we will be able to access B via A.B. A primary way to create objects in JS is to use another object, A as the new object, B’s prototype. Object B will inherit access to A’s members and we will also be able to modify B to have new members too. An example:

var c = function() {
  this.x = 3;
  this.y = 4;
  this.f = function(z) { //map an anonymous function to the name f in the map obj
     return this.x + this.y + z;
  }
  this.f2 = function(z) { //map another anonymous function to the name f2
    return this.x - this.y - z;
  }
}
var myObject = new c();
myObject.x // = 3
myObject.z // = null
var d = function() {
  this.z = 1;
}
d.prototype = new c(); //sets the prototype for objects created by c
var myOtherObject = new d();
myOtherObject.x; // = 3
myOtherObject.z; // = 1

In the example above we use prototypes to create an in­her­i­tance from object c to d. An important take away is that the new keyword sets a created object’s prototype to the value of the prototype property of the con­struc­tor function. By setting the prototype property of con­struc­tor functions we can create object in­her­i­tance hi­er­ar­chies in JS. Speaking about in­her­i­tance hi­er­ar­chies is the subject of another post for the future, for now let it suffice to say that it is another important component of OOP.

This post serves as a short and simple in­tro­duc­tion to prototypes and new in JS. I kept my words brief because there is already a wealth of well written in­for­ma­tion on the subject available at the following links:

SQL Server Identity columns and DBCC CHECKIDENT Collecting web service timing data with JMeter