I have code that looks like this:
for( var i=0; i<10; i++ ) {
var someClickableObject = new Object();
someClickableObject.index = i;
eventListenerFunction(someClickableObject, 'click开发者_C百科', function() {
alert(someClickableObject.index);
});
}
So I am creating a bunch of clickable objects, giving each a property equal to the loop index, setting a click event on the object which alerts its index property.
I want each object to alert the index i in which it was created. Instead all the objects alert 9. I think this is because the event listener forms a closure over the object which gets redefined on each iteration.
Any ideas on how to solve this?
The problem is actually the opposite of what you wrote: all the functions share the same closure. (edit — after re-reading what you wrote, I'm not sure it's "opposite" of anything; the point is that all those little functions you pass to the "eventListenerFunction" will be sharing the same variable, "someClickableObject", so at the end of the loop they'll all refer to the one created on the last iteration!)
To fix it, you need to introduce another scope somehow:
eventListenerFunction(someClickableObject, 'click', (function(obj) {
return function() {
alert(obj.index);
};
})(someClickableObject));
That introduces an anonymous function. That little function is called with the reference to your local variable, which has the effect of creating another scope. That function returns the function actually passed to that "eventListener" thing. It's got its own copy of "someClickableObject" now.
However, it's just a shallow copy. In your case, that's OK because you're creating a new object on every iteration. In practice, I've almost never had to worry about such a case; usually a shallow copy is all I need to worry about (because often it's just a counter, or a string-valued key, or something like that involved).
精彩评论