最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Please explain closures, or binding the loop counter to the function scope - Stack Overflow

programmeradmin1浏览0评论

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){/* 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.

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){/* 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.

Share Improve this question edited Jan 23, 2011 at 21:54 Marcel Korpel 21.8k6 gold badges62 silver badges80 bronze badges asked Jan 23, 2011 at 21:52 DeanDean 8,0659 gold badges31 silver badges32 bronze badges 3
  • 3 This technically doesn't involve the closure. Although i'm not entirely sure what good it does; that inner function will run immediately, and unless it returns another function, the onclick will be set to something really odd. – cHao Commented Jan 23, 2011 at 22:02
  • @cHao since this, immediate anonymous function call, is assign to onlick, it must return a function, so that returned function is a closure with "i" variable in surrounding environment. – jcubic Commented Jan 24, 2011 at 1:03
  • @jcubic: If the code is indeed setting a DOM event handler, it must return a function if it's working correctly. There's not enough code here to justify either assumption. – cHao Commented Jan 24, 2011 at 1:19
Add a ment  | 

2 Answers 2

Reset to default 7

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)

  1. 暂无评论