Possible Duplicate:
Javascript: closure of loop?
I'm having some issues with javascript closures that I can't wrap my head around... I usually find them really useful, but this time they're getting in my way.
My problem
I have a list of objects containing some information - let's call it infos
. Each object in infos
has a string property text
, and a property control
which references a control object. The control object has (among other things), a function property activate
. An example of an object in infos
could look like this:
var info = {
text: 'Some string',
control: {
activate: function() {
alert('activated!');
}
}
}
Now, I want to loop through infos
and create some new objects (actually, a DOM element, using jQuery) based on the information in the info
object.
I've tried something like this:
for (var i in infos) {
$('<a>')
.attr('href', '#')
.text(infos[i].text)
.click(function() {
infos[i].control.activate(); // This is where I get problems
});
}
Now, when executing the click handler, something (in the example above usually the variable i
) is undefined
, which causes an exception.
I have also tried the following variant:
for (var i in infos) {
var ctrl = infos[i].control;
$('<a>')
.attr('href', '#')
.text(infos[i].text)
.click(function() {
ctrl.activate(); // This is where I get problems
});
}
In this case I don't get any exception, but regardless of which item I click, it is always the last control that is activated.
My understanding of this, so far
If I've understood javascript closures correctly, this is because when the click handler function (in the second code snippet) is created with a closure that has pointers to the variables defined at the point of defining this function - infos
and i
in the first example, in addition to ctrl
in the second.
I think I could be able to resolve this, if I was able to "avoid the closure"; in other words, I'd like to refer the variables with their values as they were at the point of declaring the click handler function, rather than at the point of its execution.
Is there any way to achieve this? Or, perhaps, an even better solution to this problem?