I searched but couldn't find an answer to this seemingly easy question, so...
Suppose I have a loop in which I need to set callbacks. My callback function looks like this:
function callback(var1) { // code }
Now my loop is something like this:
for( //condition)
{
var x = something_different_开发者_如何学编程each_time;
document.getElementById('foo').addEventListener('click', function() { callback(x); }, false);
}
Now it looks like even if the loop runs n times, the anonymous function is compiled only once -- and hence every invocation of callback is called with the same argument (even though x varies in the loop every time).
I must be missing something here.. any help is greatly appreciated! :)
The problem is that the block of the for
statement doesn't creates a new scope, for that, the x
variable belongs to its enclosing scope, and all anonymous functions refer to the same variable...
Use another function to create a new lexical environment to hold the value of x
on each iteration:
for(/*condition*/) {
var x = something_different_each_time;
document.getElementById('foo').addEventListener('click', function () {
return function(y) {
callback(y);
};
}(x), false);
}
See Creating closures in loops: A common mistake
and related questions:
- JavaScript closure inside loops – simple practical example
- Doesn't JavaScript support closures with local variables?
- Access outside variable in loop from Javascript closure
- How do JavaScript closures work?
You should calculate x before calling your callback functin!
for( //condition)
{
//var x = something_different_each_time;
document.getElementById('foo').addEventListener('click', function() {
var x = something_different_each_time;
callback(x); }, false);
}
Yes, the x
will refer to the same variable in the enclosing scope, and since the function is executing later, it'll have the last value of x
. Try this:
.addEventListener(
'click',
(function (i) {
return function () { callback(i); }
})(x),
false
);
This creates a closure with the current value of x
locked inside.
精彩评论