[英]Why isn't a variable defined in for loop not visible in setTimeout function?
当我在控制台中运行以下代码时:
for(var k = 0; k < 36; k++){
setTimeout(function(k){ alert(k)}, k*5000);
}
警报显示未定义。 而且,我希望每次迭代后超时功能的延迟都会增加; 但这不会发生。 超时功能应首先在5秒后运行,然后在10秒后再运行15秒,依此类推。
为什么未定义的警报会发出警报,为什么每次迭代后延迟都不会增加?
由于k
在超时功能的本地范围内,因此它应该在其中可见。
它是undefined
因为计时器机制setTimeout
会将函数挂接到该函数,而不会调用带有任何参数的函数(默认情况下),并且已将k
声明为函数参数。 当您调用的JavaScript函数的参数少于其声明的参数时,这些参数的值是undefined
。 因此, 参数 k
遮蔽(隐藏) 循环变量 k
,您始终会看到undefined
。
要解决此问题,请不要将k
声明为函数参数:
for (var k = 0; k < 36; k++){
setTimeout(function(){ alert(k)}, k*5000);
// No k here -------^
}
示例(使用500代替5000):
for (var k = 0; k < 36; k++){ setTimeout(function(){ console.log(k)}, k*500); // No k here -------^ }
但是 ,则您必须修复一个新问题( 此问题及其答案解决的问题 ):所有这些回调看到的k
的值将相同 (36),因为它们将k
的值视为何时调用它们(后来,一旦循环结束),而不是何时创建它们。
在ES5及更早版本中,我将这样解决:
function createHandler(k) {
return function(){ alert(k)};
}
for (var k = 0; k < 36; k++){
setTimeout(createHandler(k), k*5000);
}
例:
function createHandler(k) { return function(){ console.log(k)}; } for (var k = 0; k < 36; k++){ setTimeout(createHandler(k), k*500); }
...尽管许多人会在循环中重复创建该createHandler
函数:
for (var k = 0; k < 36; k++){
setTimeout(function(innerk) {
return function() { alert(innerk); }
}(k), k*5000);
}
例:
for (var k = 0; k < 36; k++){ setTimeout(function(innerk) { return function() { console.log(innerk); } }(k), k*500); }
在ES2015 +(“ ES6”及更高版本)中,我会这样解决:
for (let k = 0; k < 36; k++){
setTimeout(() => { alert(k); }, k*5000);
}
...因为在诸如此类的for
使用let
时,它将为每次迭代创建一个新的k
,其值保持不变。
例:
// REQUIRES ES2015+ SUPPORT for (let k = 0; k < 36; k++){ setTimeout(() => { console.log(k); }, k*500); }
您可以通过两种方式传递k
参数:
for(var k = 0; k < 36; k++){
setTimeout(function(k){ alert(k); }, k * 5000, k); // but is not supported in IE9 and earlier
}
或更好地将其包装到一个函数调用中:
for (var k = 0; k < 36; k++) _setTimeout(k);
function _setTimeout(k) {
setTimeout(function(){ alert(k); }, k * 5000);
}
您可以将k传递给setTimeOut的回调函数,但它什么也不做。因此删除参数k即可。
for(var k = 0; k < 36; k++){
setTimeout(function(){ alert(k)}, k*5000);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.