Closures in a loop are causing me problems. I think I have to make another function that returns a function to solve the problem, but I can't get it to work with my jQuery code.
Here is the basic problem in a simplified form:
function foo(val) {
alert(val);
}
for (var i = 0; i < 3; i++) {
$('#button'+i).click(function(){
foo(i);
});
}
Naturally clicking on any of the three buttons will give an alert saying 3. The functionality I want is that clicking on button 1 will give an alert saying 1, button 2 will say 2 etc.
How can I make it do that?
Try this code:
Some important points here:
i
is copied in a new scope ask
, and the function returned fromfunMaker
closes aroundk
(which doesn't change in the loop), not aroundi
(which does).click
doesn't 'own' thei
, it closes over thei
of its creator, and thati
changes in the loop.funMaker
inlined, but I usually use such helper functions to make things clearer.funMaker
isk
, but that makes no difference, it could have beeni
without any problems, since it exists in the scope of the functionfunMaker
.EDIT: Fixed some punctuation.
See the bind method.
From the docs:
Or just manufacture a new function, as you describe. It would look like this:
I'm pretty sure Mehrdad's solution doesn't work. When you see people copying to a temporary variable, it's usually to save the value of "this" which may be different within an inner child scope.
@Andy solution is the nicest. But you can also use Javascript scoping to help you save the value in your closure.
You do so by creating a new scope in your loop body by executing an anonymous function.
Since the loop body is a new scope at each iteration, the index variable is duplicated with the correct value at each iteration.
Use the .each function from jquery - I guess you a looping through similar elements - so add the click using something like:
Not tested but I always use this kind structure where possible.