3

The below example was taken from the book, "Javascript: The good parts". The author says that the helper function returns a function that binds to the current value of var i.

Can anyone explain what makes it to bind the VALUE instead of REFERENCE of var i, because helper function is a closure to add_the_handler function and should only see the reference of var i:

var add_the_handlers = function (nodes) {
   var helper = function (i) {
      return function (e) {
        alert(i);
      };
    };
    var i;
    for (i = 0; i < nodes.length; i += 1) {
       nodes[i].onclick = helper(i);
    }
};
Michael Gaskill
  • 7,913
  • 10
  • 38
  • 43
Deepan
  • 559
  • 3
  • 13
  • 4
    The *i* variable in the function (e) { alert(i); }; function is referenced to the local *i* variable in the *helper* function, instead of *i* variable in the *add_the_handlers* function. – Andrey M. Jul 18 '11 at 04:40
  • This post/answer will be helpful (on pass by reference vs. value): http://stackoverflow.com/questions/6605640/javascript-by-reference-vs-by-value/6605700#6605700 – jfriend00 Jul 18 '11 at 04:59

3 Answers3

5

If you were to say:

nodes[i].onclick = function(){ alert(i) };

The function would not have it's own copy of i because i is not declared within the scope of the function.

To help you see this better I've modified your above code:

var add_the_handlers = function (nodes) {
    var helper = function(t) {
      // t is in the scope of "helper"
      return function(e){
        // e is in the scope of this anonymous function
        // and is not used
        alert(t);
      };
    };

    // Variables declared here are in the scope of "add_the_handlers"
    var i;
    for (i = 0; i < nodes.length; i += 1) {
       nodes[i].onclick = helper(i);
    }
};

In the "real world" you'll often see code like the above shortened to look like this:

var add_the_handlers = function(nodes){
    var i;
    for(i = 0; i < nodes.length; i++)
       nodes[i].onclick = (function(i){ return function(e){ alert(i); }; })(i);
};
Paul
  • 139,544
  • 27
  • 275
  • 264
  • 1
    I believe, you should return a function like this, `nodes[i].onclick = (function(i){ return function(e){alert(i);} })(i);` – Deepan Jul 18 '11 at 05:02
1

You pass the current value of i into the function helper. Inside that function the variable i, a (confusingly named) parameter to the function, is different from any other i. The closure returned thus binds to that particular i (really the [[scope]] which contains that i, but...).

Happy coding.

0

This is a guess: i is a primitive, so it's always accessed by value, and not by reference.

bbg
  • 2,892
  • 3
  • 19
  • 13
  • Nope, not at all :) It's not about object mutability, but rather about variable resolving. A new variable [[scope]] in JavaScript is only created with a new function declaration. –  Jul 18 '11 at 04:51