javascript: closure and other stuffs…

27 12 2010
While learning the closure, i found many nice articles about closure and it’s related some common issues which were discussed. Now , here i collected some of those and examined to understand the closures and it’s beautiness. Below are some examples and issues related to closures:

function cal(x){
return function (y){
return x*y;
}
}
var expr = cal(10);
var result = expr(5);
alert(expr); // Returns: function (y) {return x * y;}
alert(result); //Returns: 50

Let’s break the upper code snippet :

  1. When the cal function is called, it returns a function.
  2. That function closes the context and remembers what the parameter x was at exactly that time (i.e. 10 in the code above)
  3. When the result of calling the cal function is assigned to the variable expr, it will always know what x was when it was initially created.
  4. The expr variable above refers to a function which will always multiply the value 10 to what is being sent in.
  5. That means when expr is called with a value of 10, it will multiply 10 with 5, and return 50.

So, in the world of JavaScript, the expr function actually looks like this in reality or conceptually:
function cal (y) {
return 5 * y;
}

It is important to understand that the inner function has access to the actual variables of the outer functions and not copies in order to avoid the following problem:

Code View:

// BAD EXAMPLE
// Make a function that assigns event handler functions to an array of nodes the wrong way.
// When you click on a node, an alert box is supposed to display the ordinal of the node.
// But it always displays the number of nodes instead.
var add_the_handlers = function (nodes) {
var i;
for (i = 0; i < nodes.length; i += 1) {
nodes[i].onclick = function (e) {
alert(i);
}
}
};
// END BAD EXAMPLE

The add_the_handlers function was intended to give each handler a unique number (i). It fails because the handler functions are bound to the variable i, not the value of the variable i at the time the function was made:

Code View:

// BETTER EXAMPLE
// Make a function that assigns event handler functions to an array of nodes the right way.
// When you click on a node, an alert box will display the ordinal of the node.
var add_the_handlers = function (nodes) {
var i;
for (i = 0; i < nodes.length; i += 1) {
nodes[i].onclick = function (i) {
return function (e) {
alert(i);
};
}(i);
}
};

Now if we want to see any practical code view regarding the above issue which is noted from the Douglas Cockford’s Javascript: The Good Parts book, we can understand the infamous loop problem and the power of closure.

PRACTICAL EXAMPLE:

Incorrect Reference

Let’s take a look at this faulty code, which creates 5 a elements, adds the value of i as a text to each element and an onclick which is expected to alert the value of i for that link, i.e. the same value as in the a element’s text. It then appends them to your document body:
function addLinks () {
for ( var i=0, link; i<5; i++) {
link = document.createElement("a");
link.innerHTML = "Link "+ i;
link.onclick = function() {
alert(i);
};
document.body.appendChild(link);
}
}
window.onload = addLinks;

Each a element gets the correct text, i.e. “Link 0″, “Link 1″ and so on. But whichever link you click, it alerts the number “5″. Oh my God, why? The reason for this is that the variable i get its value increased with 1 for each iteration of the loop, and since the onclick event isn’t being executed, just applied to the a element, it adds up.

Therefore, the loop continues until i is 5, which is the last value of i before the function addLinks exits. Then, whenever the onclick event is actually being triggered, it takes the last value of i.

Working Reference

What you want to do instead is create a closure, so that when you apply the value of i to the onclick event of the a element, it gets the exact value of i at just that moment in time. Like this:
function addLinks () {
for(vari=0, link; i<5; i++) {
link = document.createElement("a");
link.innerHTML = "Link "+ i;
link.onclick = function (num) {
return function() {
alert(num);
};
}(i);
document.body.appendChild(link);
}
}
window.onload = addLinks;

With this code, if you click the first a element it will alert “0″, the second “1″ etc; just what you probably expected with the first code I showed you to do. The solution here is that the inner function of what’s applied to the onclick event create a closure where it references the parameter num, i.e. what the i variable is at just that time.

That function then closes with that value safely tucked away, and can then return its corresponding number when the onclick event is being called.

Source from:  robertnyman,Douglas Cockford

About these ads

Actions

Information

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




Follow

Get every new post delivered to your Inbox.

%d bloggers like this: