3

Possible Duplicate:
Javascript infamous Loop problem?

For some reason I get "6" inside my function here for every div element:

for(var i = 1; i <= 5; i++){
  $('<div class="e-' + i + '"></div>').appendTo(something).click(function(){
    alert(i);  // <-- it's 6. wtf??
  });
}

instead of 1, 2, 3, etc.

The class on the other hand it appears to be correctly set..

What am I doing wrong?

2

2 Answers 2

10

Your for loop is being executed at page load time. The alert only fires when there's a click event which is happening after the for loop has finished. Hence the value of i is now 6.

1) Page loads, for loop does its stuff...

2) Sometime later a click event is fired. the value of i at this time is 6 because the forloop has already completed.

0
5

The problem is that you need to create a closure to capture the value of i at the time you bind the click function.

Try this:

for(var i = 1; i <= 5; i++)
{
  $('<div class="e-' + i + '"></div>')
    .appendTo(something)
    .click(function(value)
    { 
      return function() { alert(value) };
    }(i));
}
5
  • Why not use an anonymous function? It looks better. Commented Apr 25, 2012 at 14:17
  • also the var fn inside the loop is misleading as there is no block scope in js.
    – Yoshi
    Commented Apr 25, 2012 at 14:18
  • Cool, didn't know about the lack of block scope. Either way, my unedited answer works fine.
    – wsanville
    Commented Apr 25, 2012 at 14:22
  • Eww! I prefer to do it cleaner still: for(var i = 1; i <= 5; i++){createWidget(i);} and move the entire jQuery statement into createWidget or whatever. Why create an anonymous function every iteration? Commented Apr 25, 2012 at 15:23
  • Why create an anonymous function every iteration? You do that to capture the value of i each time. That's what a closure does.
    – wsanville
    Commented Apr 25, 2012 at 15:37

Not the answer you're looking for? Browse other questions tagged or ask your own question.