javascrip closure

First, a very very good article explaining CLOSURE

Second, I like this answer in Stackoverflow:

A function in JavaScript is not just a reference to a set of instructions (as in C language) but also includes a hidden data structure which is composed of references to all nonlocal variables it uses (captured variables). Such two-piece functions are called closures. Every function in JavaScript can be considered a closure.

Closures are functions with a state. It is somewhat similar to “this” in the sense that “this” also provides state for a function but function and “this” are separate objects (“this” is just a fancy parameter, and the only way to bind it permanently to a function is to create a closure). While “this” and function always live separately, a function cannot be separated from its closure and the language provides no means to access captured variables.

Because all these external variables referenced by a lexically nested function are actually local variables in the chain of its lexically enclosing functions (global variables can be assumed to be local variables of some root function), and every single execution of a function creates new instances of its local variables, it follows that every execution of a function returning (or otherwise transferring it out, such as registering it as a callback) a nested function creates a new closure (with its own potentially unique set of referenced nonlocal variables which represent its execution context).

Also, it must be understood that local variables in JavaScript are created not on the stack frame but in the heap and destroyed only when no one is referencing them. When a function returns, references to its local variables are decremented but can still be non-null if during the current execution they became part of a closure and are still referenced by its lexically nested functions (which can happen only if the references to these nested functions were returned or otherwise transferred to some external code).

 

Let’s take a look at this small sample of a function that creates and returns another function. The returned function accepts one string argument and returns another string repeating the argument a number of times.

  1. function makeRepeater(times){
  2.     return function(text){
  3.         var message = ;
  4.         for (var i=0; i < times; i++) {
  5.             message += text + ‘ ‘;
  6.         }
  7.         return message;
  8.     };
  9. }

Let’s now write some code that uses that function.

  1. var threeTimes = makeRepeater(3);
  2. var fourTimes = makeRepeater(4);
  3. alert( threeTimes(‘hi’) );
  4. // => ‘hi hi hi ‘
  5. alert( fourTimes(‘hi’) );
  6. // => ‘hi hi hi hi ‘

Nothing spectacular, right? But look closely. The function returned by makeRepeater contains a reference to times, which is a local variable ofmakeRepeater. When we call threeTimes or fourTimes the makeRepeater call has already returned and times should be out of scope. Or should it?

Extra life for your local scope

You may try to argue and say that the times inside threeTimes is not a reference to the times from makeRepeater, but just a copy of that value. Well, sadly I’ll have to prove you wrong. Let’s modify our code just a little.

  1. var times;
  2. function makeRepeater(){
  3.     return function(text){
  4.         var message = ;
  5.         for (var i=0; i < times; i++) {
  6.             message += text + ‘ ‘;
  7.         }
  8.         return message;
  9.     };
  10. }
  11. times = 3;
  12. var threeTimes = makeRepeater();
  13. times = 4;
  14. var fourTimes = makeRepeater();
  15. alert( threeTimes(‘hi’) );
  16. // => ‘hi hi hi hi ‘  —> What?!?!
  17. alert( fourTimes(‘hi’) );
  18. // => ‘hi hi hi hi ‘

If it’s not clear yet, let me write it down for you. The returned function really keeps a reference to any outside values it will need when invoked. In our original example, it kept a reference to the times local variable at the time it was produced. If we had created other local variables insidemakeRepeater they would also become available inside the returned function. In other words, all the scope created during the call tomakeRepeater will be preserved for the returned function. This happens when the returned (or inner) function has a reference to anything defined in the parent (or outer) function, i.e. the parent local scope. When this happens, we say that a closure has been created.

Closures can be tricky

It’s important to understand the mechanics of closures to avoid subtle bugs in our code. Look at this piece of code, adapted from a real bug I had to fix.

  1. <input type=“button” value=“Button 1” id=“btn1”>
  2. <input type=“button” value=“Button 2” id=“btn2”>
  3. <input type=“button” value=“Button 3” id=“btn3”>
  4. “text/javascript”>
  5.     function createEventHandlers(){
  6.         var btn;
  7.         for(var i=1; i
  8.             btn = document.getElementById(‘btn’ + i);
  9.             btn.onclick = function(){
  10.                 alert(‘Clicked button #’ + i);
  11.             }
  12.         }
  13.     }
  14.     createEventHandlers();

If you put this code in a page and click the three buttons you will see that all of them will show the message “Clicked button #4”. Armed with our understanding of closures we can immediately understand that this bug is being caused by that reference to i used inside the event handler. We can fix that.

  1. function createEventHandlers(){
  2.     var btn;
  3.     for(var i=1; i <= 3; i++){
  4.         btn = document.getElementById(‘btn’ + i);
  5.         btn.onclick = createOneHandler(i);
  6.     }
  7. }
  8. function createOneHandler(number){
  9.     return function() {
  10.         alert(‘Clicked button #’ + number);
  11.     }
  12. }

The above code works because we are not creating functions inside the for loop, hence not producing closures on the same local scope. There is a different set of closures being produced by createOneHandler, but those are not pointing to the same parent scope. Each of these three new closures contain a different scope, created by each call to createOneHandler

Closing thoughts

Closures, of course, are not an exclusive feature of JavaScript. It’s a very important trait of functional languages. Even in C#, when we use lambdas, closures are created — many times without us noticing.

The key to properly using closures in our code is to pay attention to locally scoped values from the outer function being used in the body of the inner function. Most of the times this will work as intended by the developer but, when it doesn’t, stop and check if more than one closure is sharing the same local scope or if these local values are changing between the inner function creation and its invocation.

FROM HERE

Documentation and examples in Mozilla

Advertisements

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