Just JavaScript - Object Construction
Written by Ian Elliot   
Thursday, 21 August 2014
Article Index
Just JavaScript - Object Construction
Late and early binding
The Constructor

 

Private Properties

It should be obvious now that closure can be used to create private properties for objects, but it is worth exploring a little more. 

For example, you can create a private property for the point object using something like:

Point=function(x,y){
 var obj={};
 var myPrivateData=10;
 obj.getPriv= function(){
  return myPrivateData;
 }:

var myPoint= new Point(1,2); alert(myPoint.getPriv()); 

Where the code has been stripped down to just what is needed to demo a private variable. In this case the getPriv function can access myPrivateData because of closure and so everything works. However any attempt to directly access the variable fails because there is no closure in operation and it is not a property of the constructed object. That is both:

alert(myPoint.myPrivateData);

and

alert(myPrivateData);

fail.

The private variable pattern is well known but it works for methods as well and this seems to be less well used. 

For example if I want to create a private function that only the object can use all you have to do is declare it as a local variable within the object factory:

Point=function(x,y){ var myPrivateData=10;
 var obj={}; 
 var myPrivateAdd=function(a,b){ 
  return a+b; 
  };
 
  obj.add=function(){
   return myPrivateAdd(1,2);
 };
};

In this case myPrivateAdd is accessible from the object constructed because of closure which means it can be called from within any method of the object. Again the myPrivateAdd function cannot be called outside of the object because it is not a property and only available as a closure inside the object. 

Notice that a private function can make use of private variables as these are made available to it by closure within the object itself.

Using this

In the previous example we made use of a private variable to store a reference to the object being created. This allowed the methods of the object to refer to its properties. 

You could have achieved more-or-less the same result using this as when you create an object literal. 

For example:

Point=function(x,y){ 
 var obj={};
 obj.x=x; 
 obj.y=y; 
 obj.add=function(){
          return this.x+this.y; 
         }; 
 return obj; 
};

If you try this out you will find that it give the same result as using the private variable obj.

That is:

var myPoint=Point(1,2);
myPoint.x=4;
alert(myPoint.add());

works and displays the answer 6 as before.

However this works in a very different way from the private variable obj. 

When you call the method

myPoint.add();

the system sets this to reference the same object as myPoint and hence when the code is obeyed expression like this.x is the same thing as myPoint.x which is what you want.

You can see that the private variable obj is an alternative to using this and perhaps obj isn't a good name to use for it. However, it has emphasised the fact that it isn't anything special and just a reference to the object instance that the factory object is creating.

To make the similarity between obj and this clearer you could use the name self, which is commonly used to make a self reference in other languages.   

Point=function(x,y){ 
 var self={};
 self.x=x; 
 self.y=y; 
 self.add=function(){
          return self.x+self.y; 
         }; 
 return self; 
};

Keep in mind that self isn't a keyword like this, it is just another variable. 

Late And Early Binding

As with objects created as object literals using this to convert a Function property into a method produces a late bound method. That is the association between the Function object and the object it is a property of is only established at run time. 

You can see that this is true if you create another reference to the Function object.

Point=function(x,y){ 
 var self={};
 self.x=x; 
 self.y=y; 
 self.add=function(){
          return this.x+this.y; 
         }; 
 return self; 
};

For example:

var myPoint=Point(1,2);
myPoint.x=4;
var myFunc=myPoint.add;
alert(myFunc());

The new variable myFunc references the same function object as myPoint's add property. However when called as myFunc this is set to the calling context which in this case is the global object. Now when the function tries to evaluate this.x or this.y it looks for global variables of the same name and there aren't any. This is why the result is NaN. 

Now consider using a local private variable created by closure in place of this:

Point=function(x,y){ 
 var self={};
 self.x=x; 
 self.y=y; 
 self.add=function(){
          return self.x+obj.y; 
         }; 
 return self; 
};

Now when you try the same thing:

var myPoint=Point(1,2);
myPoint.x=4; 
var myFunc=myPoint.add; 
alert(myFunc());

the value of the local call context doesn't come into it. Now all that matters is what the obj variable references and this is always the object created by the object factory - hence the result is 6. 

if you use a local variable in place of this in creating methods within an object factory the result is early bound methods. If you use this the result is late bound methods.

Constructors

Object factories are a completely general idea. You write a function that returns an object. JavaScript has some features which are specifically defined to make object factories more useful and perhaps easier to use. 

A constructor is an object factory that you use in conjunction with the operator new. 

For example:

var myPoint=new Point(1,2);

Using a constructor makes JavaScript look much more like other object oriented languages which tend to use new and a class based constructor. 

What difference does the use of new in front of an object factory make?

There are quite a few differences. The first and most important is that when the object factory is called this isn't set to the call context but to a newly created empty object.

You can think of new as adding;

this={};

to the start of the object factory.

What this means is that instead of having two write 

var obj={};

or 

var self={}

you can just use this as a reference to the newly created empty object. 

Another important change is that a constructor automatically returns this as a reference to the object that has been created.

For example, if we use a constructor to create a point object then the code would be:

Point=function(x,y){ 
 this.x=x; 
 this.y=y; 
 this.add=function(){
          return this.x+this.y; 
         }; 
};

This works in the same way as our plan object factory version except for the fact that you have to put new infront when you use it. For example:

var myPoint=new Point(1,2);

Notice that in the constructor this has two distinct meanings. The first is when it is used to refer to the object being constructed e.g.

this.x=x;

The second is when it appears within a method definition. For example

return this.x+this.y;

As the code within a method definition isn't being executed the current value of this has no effect. When the code is executed this in the method is set to the call context and everything works.



Last Updated ( Sunday, 10 May 2015 )