Javascript Closures

Introduction

Following on from my previous article on javascript object creation and objects, arrays and associative arrays, I am now going to cover the concept of call-scope and closures in JavaScript.

Understanding scopes

In common with most languages, JavaScript has the concept of scope. Scope defines what objects are visible to a body of code at runtime. In JavaScript script the variables in scope are those in scope at the time the function was created or assigned. Variables defined in the global scope are visible to all code so long as the variable or object has been declared prior to the code in question:

 
var x = 1;

function sumFunc(y)
{   
    alert(x+y);
}

sumFunc(3);

//the value of x is visible within the function sunFunc().

JavaScript code is run in the context of a call object, which contains references to all accessible variables. Each new function or frame results in a new call object being chained onto the previous (parent) one, with the properties of the parent scope being available in the child scope. Additionally, any variables declared within the new function, and any parameters, will be properties on the child scope. If a child scope defines variables or arguments that have the same name as a property of the parent scope, they will hide the parent scope
s instance.

Examining what is going on above, when sumFunc is called, the global scope contains x. The child scope has inherited the property ‘x’ and added a new property ‘y’ which was in the parameters. When the function ends, there will be no more references to the child scope and it will be disposed of by the garbage collection. The value ‘y’ will not be available to any code. Consider if we change the code slightly:

 
var x = 1;

function sumFunc(y)
{   
    return function(){alert(x+y);};
}

var f1 = sumFunc(3);
var f2 = sumFunc(4);

f1();
f2();

If you run this code, you will get 4 and 5 displayed, respectively. What is happening is that each invocation of sumFunc results in a new instance of the nested function being created in the current scope, with their unique value of the parameter ‘y’. Exiting the function has not led to the scope being destroyed because the nested function in it’s construction attains a reference to the current scope.

Where closures are interesting is that although JavaScript does not have the concept of private variables, the use of closures can synthesize private members successfully. Consider the following script. I want to create a function that returns the next number whenever it is called.

I create a function that defines a local variable iNext and return from the function a nested function that refers back to iNext. Any function I create in this child scope will always be able to reference the value of iNext. Now when uniqueID is called, the function can reference the variable iNext because it was in scope when the function was created (it doesn’t matter if it is in scope when the function is called).

 
var uniqueID = (function(){
    var iNext = 0;   
    return function(){return iNext++;};
})();

alert(uniqueID());
alert(uniqueID());
alert(uniqueID());
alert(uniqueID());

The really interesting point is that iNext is not programmatically accessible in code. This technique can be extended to synthesize private functions. In the following script the function getSquare is not accessible through code once the self-executing function has run.

 
var uniqueID = (function(){
    var iNext = 0;   
    var iPower = 0;
    function getSquare(){
        return Math.pow(iNext,iPower);
    }
    
    return function(){return getSquare(iNext+=2, iPower++);};
})();

alert(uniqueID());
alert(uniqueID());
alert(uniqueID());
alert(uniqueID());


The closure of a function is evaluated when the function is assigned to a variable. Consider the following code. When the prototype method area is assigned to the newly created object, ‘this’ is in scope and is the object being constructed. When the function is copied into a global variable, the value of ‘this’ is evaluated again and this time it is the global window object, which does not have a value for width or height.

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

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

//create a new rect object
var rect= new Rect(10,5);

//this will output 50
alert(rect.area());

var copyOfArea = rect.area;

//this will alert NaN
alert(copyOfArea());

If we were to add two global variables width and height to the global window object, then copyOfArea would be the product of those two numbers.

It can be seen now why it is necessary to prefix all calls to properties and function for an object with the ‘this’ keyword. At the time of construction, ‘this’ is the object being constructed and all the properties relate to that instance only. That is how properties and function make up a javscript object – through the shared call context when the object is constructed.

Be aware it is important to remember that when coding event handlers that the value ‘this’ is not taken for granted. Consider the following script.

 
function MyObj(){
  this.SpecialName = "myobj";
 
    jQuery('#someButton').click(function(){        
        alert(this.SpecialName);
    });
};

var r = new MyObj();

If a button with Id “someButton” was clicked, the value of this.SpecialName would be undefined. That is because the value of “this” is different to the value of “this” when the object was created.

The correct approach for referencing an object from within a delegated function is take a local reference to “this” and have the function use it instead as below:

 
function MyObj(){
  this.SpecialName = "myobj";
   var _this = this;
    jQuery('#someButton').click(function(){        
        alert(_this.SpecialName);
    });
};

var r = new MyObj();

Conclusion

This post has covered the basics of closures in JavaScript. It was shown that functions are a combination of both the their code and the context or scope in which they are called. Interesting closures can be created by returning nested functions from functions containing local variables or methods, and in doing do private members can be synthesized. It is important to keep in mind how scopes can result in the value of “this” being overwritten in event handlers, and a safe approach under these circumstances is refer to a local reference of the “this” object prior to declaring the event handler.

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

One Response to Javascript Closures

  1. I didn’t get what part of the examples of the uniqueID variable/function contributed to the effect of synthesized private members/functions. What components of the code made this happen?

    Also, I’ve used this before, but I still don’t understand why or what it’s called or does (the use of “open/close” parenthesis after a function) in reference to the same examples of unqueID.

    Why does the function assigned to the variable, uniqueID, have to be enclosed in parenthesis, then followed by the mysterious empty “open/close” parenthesis?

    Thanks, in advance.

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