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

后端 未结 2 396
孤城傲影
孤城傲影 2021-02-04 17:59

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++){
   some         


        
相关标签:
2条回答
  • 2021-02-04 18:41

    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.

    0 讨论(0)
  • 2021-02-04 18:42

    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 讨论(0)
提交回复
热议问题