Ligação a variables ​​JavaScript e loop

Considere esse loop:

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

A saída é:

 => 2 => 2 

Eu gostaria que fosse: 0, 1. Eu vejo duas maneiras de corrigir isso:

Solução # 1.

Este baseado no fato de que podemos passar dados para setTimeout.

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

Solução # 2.

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

Há alguma outra alternativa?

Não é realmente nada mais do que as duas maneiras que você propôs, mas aqui está outra

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

Essencialmente, você precisa capturar o valor da variável em um fechamento. Esse método usa uma function anônima imediatamente invocada para capturar o valor da variável externa em uma variável local m .

Aqui está uma demonstração de trabalho para brincar. adicionar / editar na URL para ver o código

Com a palavra-chave let você pode contornar isso completamente:

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

Semelhante à solução acima, mas auto invocando dentro da function setTimeout

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

Semelhante às outras soluções, mas na minha opinião mais limpa:

 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) } 

Isso mantém o mesmo nome de variável para a captura e o faz para todo o loop, separando-o da lógica da configuração de tempo limite. Se você quiser adicionar mais lógica dentro do bloco, você pode fazer isso trivialmente.

A única coisa que eu não gosto sobre a solução é a repetição de "it" no final.