JavaScript variable binding and loop

2019-01-01 16:44发布

问题:

Consider such loop:

for(var it = 0; it < 2; it++)
{
    setTimeout(function() {
        alert(it);
    }, 1);
}

The output is:

=> 2
=> 2

I would like it to be: 0, 1. I see two ways to fix it:

Solution # 1.

This one based on the fact that we can pass data to setTimeout.

for(var it = 0; it < 2; it++)
{
    setTimeout(function(data) {
        alert(data);
    }, 1, it);
}

Solution # 2.

function foo(data)
{
    setTimeout(function() {
        alert(data);
    }, 1);
}

for(var it = 0; it < 2; it++)
{
    foo(it);
}

Are there any other alternatives?

回答1:

Not really anything more than the two ways that you have proposed, but here\'s another

for(var it = 0; it < 2; it++)
{
    (function() {
        var m = it;   
        setTimeout(function() {
            alert(m);
        }, 1);
    })(); 
}

Essentially, you need to capture the variable value in a closure. This method uses an immediately invoked anonymous function to capture the outer variable value it in a local variable m.

Here\'s a Working Demo to play with. add /edit to the URL to see the code



回答2:

With the let keyword you can get around this completely:

for(let it = 0; it < 2; it++)
{
    setTimeout(function() {
        alert(it);
    }, 1);
}


回答3:

Similar to above solution but self invoking inside of setTimeout function

for(var it = 0; it < 2; it++)
{
    setTimeout(function(cur) {
        return function(){
           alert(cur);
        };
     }(it), 1);
 }


回答4:

Similar to the other solutions, but in my opinion cleaner:

for (var it = 0; it < 2; it++) {
  // Capture the value of \"it\" for closure use
  (function(it) {
     setTimeout(function() {
       alert(it);
     }, 1);
  // End variable captured code
  })(it)
}

This keeps the same variable name for the capture, and does it for the entire loop, separating that from the logic of the timeout setup. If you want to add more logic inside the block, you can trivially do that.

The only thing I don\'t like about the solution is the repeat of \"it\" at the end.