0
for (var i=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);
}

Since the nested function is a closure it has a reference to the num argument ,the num argument at the end of the loop is 4 .Now when the first element gets clicked why does it alerts 1 ?It should alert 4 .What is the reason for alerting 1 ?Dont it reference to num argument?or what is the reason?

But here the case is different:

function foo(x) {
    var tmp = 3;
    return function (y) {
       alert(x + y + (++tmp));
    }
}
var bar = foo(2); // bar is now a closure.
bar(10);

The above function will alert 16, because bar can still refer to arg x and tmp, even though it is no longer directly inside the scope.

This proves that the closure also have reference to arguments value than why the above code not alerting 4 everytime?

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Maizere Pathak.Nepal
  • 2,383
  • 3
  • 27
  • 41
  • 3
    It's alerting `1` when clicking on the first element since you are passing the argument `i` at the current iteration to the inner `onclick` function which has the argument `num`. – Anthony Forloney Apr 03 '13 at 17:50
  • 1
    [This question on SO](http://stackoverflow.com/questions/111102/how-do-javascript-closures-work) has some great answers that can help you understand closures – excentris Apr 03 '13 at 17:53
  • 1
    It actually should be alerting 0, since thats the first # that you pass – Ben McCormick Apr 03 '13 at 17:57

2 Answers2

3
  for (var i=0, link; i<5; i++) {  //i starts at 0 and iterates up to 4
        link = document.createElement("a");
        link.innerHTML = "Link " + i;


         link.onclick = function (num) {
            //num is never changed within this function, and is equal
            //to the value of i when it was passed in

            return function () { alert(num);};

        }(i);  //i is passed here
        //that sets num to the current value of i for each link

        document.body.appendChild(link);
   }

For the first link num will be 0, because i was one when it was passed to the outer function. i is then iterated for each turn of the loop and will be a different value for each link.

The pattern here is a very common pattern for preserving the current value of a loop iteration in callbacks/event bindings.

Ben McCormick
  • 25,260
  • 12
  • 52
  • 71
0

What you're doing is the classic example to avoid that clicking on the first element will give you 4 instead of 1, which should be the most expected value.

If you want it to alert 1, then just do this:

link.onclick = function() {alert(i);};

But honestly, what would be the point of this? All 4 links would alert 4...

MaxArt
  • 22,200
  • 10
  • 82
  • 81