Javascript Object Instantiation and Prototypes

This is part of series on javascript mechanics I’m writing – mainly for my own benefit but also to help those shy server developers out there venture into the mysterious land of the ‘client side’. In my last post I covered the basics of what is a javascript object, and in my next post I am going to cover javascript closures but today I’m going to cover object construction and initialisation.

Following on from my previous post, I now want to explain javascript objects in some greater detail. In my previous post I had some script that created an object as follows:

 
var rect = new Object();

rect.width = 10;
rect.height = 30;

rect.area = function () {
    return this.width * this.height;
};

This script is invoking the Object type’s instance factory method that returns a new Object instance. This is equivalent defining a function called Object() and calling in the context of a newly created object as follows:

 
function Object(){
  return this;
}

var rect = {};

Object.apply(rect);

.....

So what is really going on here?

What the new keyword does is instantiates an empty object ({}) and calls the specified constructor function in the context of the newly created object. Once you understand this, you are well on your way to becoming a javascript legend!

So you can see that every javascript starts the same – as an empty object {}, it is what method gets called in conjunction with new keyword that defines the properties of the resultant object. To demonstrate what I mean, consider the following script:

 

var objectCount = 1; 

Object = function(){ 
  this.id = objectCount++; 
}; 

var obj = new Object(); 
//this will have a value of 1
alert(obj.id); 

var otherobj = {}; 
//this object did not get run though the object factory, so this will be undefined
alert(otherobj.id); 

If you run this, obj.id will have some integer value. However otherobj.id is undefined, becuase it’s instance has not been run though the object factory. If I now do this..

 
var objectCount = 1; 

Object = function(){ this.id = objectCount++; }; 

var otherobj = {}; 
//apply the factory method in the context of the new object 

Object.apply(otherobj); 

//the object now has the property set and equal to 2 
alert(otherobj.id); 

otherobj.id now has a integer value.

So to reiterate, in javascript all object are created equal. What the new operator does is to apply a factory method to the newly instantiated object.

Now we understand what a object fatcory is, we can start to create them so we get uniformly created objects. First we’ll create a Factory method for a mythical but possibly useful Rect class as follows:

 

function Rect(width,height){
  this.width = width;
  this.height = height;
  this.area = function () {
    return this.width * this.height;
  };
}

var rect= new Rect(10,5);

alert(rect.area());

var rect2 = new Rect(5,1);

alert(rect2.area());

alert(rect2.area == rect.area);

Here you’ll note the use of parameters in the constructor. Again, what the new keyword results in is the construction of an empty object {}, which is then set as the “this” context for the factory method that is called with the two parameters. If you run this script, you’ll see that the for each instance of Rect created, they both have a method area defined, but they each have their own version.

This may initially seem bizarre, but it should be remembered that functions in javascript are objects that can be assigned to properties at runtime, much like delegates in C#.

This is probably sub-optimal, so javascript has the concept of a prototype. The prototype of a constructor function is a special property of the function that is used in the object construction pipeline to initialise objects prior to their constructor being run. Each property of the prototype object is shallow copied to the new object (from my previous post, you’ll recall javascript objects are more or less associative arrays whose properties can be altered freely at runtime).

The psudeo-code for object construction then becomes

  1. Create an empty object {}
  2. Copy all the properties of the prototype object of the constructor function to the newly created object
  3. Pass the object to the constructor function to perform any initialisation

Revisiting the script from above

 

function Rect(width,height){
  this.width = width;
  this.height = height;;
};

/* Add to the prototype */
Rect.prototype.area  = function () {
   return this.width * this.height;
};

var rect= new Rect(10,5);

alert(rect.area());

var rect2 = new Rect(5,1);

alert(rect2.area());

alert(rect2.area == rect.area);

When this code is run, it will be seen that both rects have the function srea and they are in fact the same function-object. This makes sense becuase when the prototype is applied, the copies of the function are by reference.

Note that the prototype of an constructor function can be altered at any point. If we re-assign the area of our rect, then new instances of rect will have a different area method to the first few instances. Changing the prototype does not affect instances of created objects.

Being objects, the popular way to define a prototype is to use object-notation. The provides for a succinct collation of each function to be assigned to the new object. The following sample demonstrates:

 

function Rect(width,height){
  this.width = width;
  this.height = height;;
};

/* Add to the prototype */
Rect.prototype = {
  area:function(){
       return this.width * this.height;
   },
   diagonal:function(){
       return Math.sqrt( Math.pow(this.width,2) + Math.pow(this.height,2) );
   }
};


var rect= new Rect(10,5);

alert(rect3.diagonal());

One thing to keep in mind when creating prototype objects is the need to reference object properties using the keyword this. This is to deal with closures, which will the topic of my next javascript in-depth topic.

Conclusion

In this post I have the fundamentals of objects and their instantiation in Javascript.

Advertisements
This entry was posted in Javascript and tagged , . Bookmark the permalink.

5 Responses to Javascript Object Instantiation and Prototypes

  1. Muhammad Adeel Zahid says:

    Great job done 🙂 few questions to ask
    1- could not find your name
    2- when your next post will be up on closures in javascript
    Today i visited your blog for first time and its been a great experience. Thanks for your efforts.

  2. Pingback: Javascript Closures | XHalent Coding…

  3. “Note that the prototype of an constructor function can be altered at any point. If we re-assign the area of our rect, then new instances of rect will have a different area method to the first few instances. Changing the prototype does not affect instances of created objects.”

    This is the case when replacing the existing prototype object
    Rect.prototype = {
    area:function()…

    It is not the case if you assign a new function to the existing prototype object
    Rect.prototype.area = function()…

    At least, unless I’ve got something in my own tests wrong 😉 . Although, this would seem to be consistent with the way JS passes references around.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s