JavaScript变量绑定和循环
考虑这样的循环:JavaScript变量绑定和循环,javascript,loops,closures,scope,Javascript,Loops,Closures,Scope,考虑这样的循环: for(var it = 0; it < 2; it++) { setTimeout(function() { alert(it); }, 1); } 我希望它是:0,1。我认为有两种方法可以解决这个问题: 解决方案1 这是基于我们可以将数据传递给setTimeout的事实 for(var it = 0; it < 2; it++) { setTimeout(function(data) { alert(da
for(var it = 0; it < 2; it++)
{
setTimeout(function() {
alert(it);
}, 1);
}
我希望它是:0,1。我认为有两种方法可以解决这个问题:
解决方案1
这是基于我们可以将数据传递给setTimeout的事实
for(var it = 0; it < 2; it++)
{
setTimeout(function(data) {
alert(data);
}, 1, it);
}
解决方案2
function foo(data)
{
setTimeout(function() {
alert(data);
}, 1);
}
for(var it = 0; it < 2; it++)
{
foo(it);
}
还有其他选择吗?除了您提出的两种方法之外,实际上没有其他选择,但这里有另一种
for(var it = 0; it < 2; it++)
{
(function() {
var m = it;
setTimeout(function() {
alert(m);
}, 1);
})();
}
本质上,您需要捕获闭包中的变量值。此方法使用立即调用的匿名函数捕获外部变量值,并将其保存在局部变量m中
这里有一个游戏。添加/编辑URL以查看代码,类似于上述解决方案,但在setTimeout函数内部自调用
for(var it = 0; it < 2; it++)
{
setTimeout(function(cur) {
return function(){
alert(cur);
};
}(it), 1);
}
使用let关键字,您可以完全绕过此问题:
for(let it = 0; it < 2; it++)
{
setTimeout(function() {
alert(it);
}, 1);
}
与其他解决方案类似,但我认为:
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)
}
这将为捕获保留相同的变量名,并为整个循环保留相同的变量名,从而将其与超时设置的逻辑分离。如果您想在块内添加更多逻辑,您可以简单地这样做
我唯一不喜欢这个解决方案的地方就是在结尾重复它。+1。但是,您可以通过将方法签名更改为:functionm{/*code*/}it+1,但有人能解释一下为什么这样行吗@digorydoo循环中声明的函数用括号括起来,后面是一组括号,这些括号用于立即调用函数。由于变量的作用域是声明它们的函数,或者如果不是在函数中声明,则是全局作用域,因此每次迭代中的值都被分配给m变量,该变量的作用域是立即执行的函数。我理解语法,但是我很困惑,如果变量“it”被复制到其他变量“m”中而不是仅仅使用“it”,为什么会有区别呢@digorydoo因为它的值在每次迭代时都会改变,如果每次迭代中的值没有在每次迭代时立即执行的函数的上下文中捕获,然后将使用传递给setTimeout的函数执行时存在的值。将它的值赋给m将捕获闭包中每个迭代中的值,从而在传递给setTimeout的函数执行时从每个迭代中发出预期值的警报。这有帮助吗?但在javascript中并没有名为let的关键字,它在typescript i中think@PardeepJain在JS的ES6版本中引入了let关键字。
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)
}