开发者

Please explain closures, or binding the loop counter to the function scope

I've seen programmers assign events listeners inside loops, using the counter. I believe this is the syntax:

for(var i=0; i < someArray.length; i++){
   someArray[i].onclick = (function(i){/开发者_StackOverflow* Some code using i */})(i);
}

Could someone please explain the logic behind this, and this weird syntax, I've never seen this:

(function(i))(i);

Many thanks for your time and patience.


The (function(i))(i) syntax creates an anonymous function and then immediately executes it.

Usually you'll do this to create a new function every time through the loop, that has its own copy of the variable instead of every event handler sharing the same variable.

So for example:

for(int i = 0; i < 10; i++)
    buttons[i].click = function() { doFoo(i); };

Often catches people out, because no matter what button you click on, doFoo(10) is called.

Whereas:

for(int i = 0; i < 10; i++)
    buttons[i].click = (function(i){ return function() { doFoo(i); };)(i);

Creates a new instance of the inner function (with its own value of i) for each iteration, and works as expected.


This is done because JavaScript only has function scope, not block scope. Hence, every variable you declare in a loop is in the function's scope and every closure you create has access to the very same variable.

So the only way to create a new scope is to call a function and that is what

(function(i){/* Some code using i */}(i))

is doing.

Note that your example misses an important part: The immediate function has to return another function which will be the click handler:

someArray[i].onclick = (function(i){
    return function() {
       /* Some code using i */
    }
}(i));

The immediate function is nothing special. It is somehow inlining function definition and function call. You can replace it by a normal function call:

function getClickHandler(i) {
    return function() {
         /* Some code using i */
    }
}

for(var i=0; i < someArray.length; i++){
   someArray[i].onclick = getClickHandler(i);
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜