为什么不是't在for循环中定义的变量在setTimeout函数中不可见
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);
}
相关文章:
- Angularjs 更新 setTimeout 中的范围变量不起作用
- 被覆盖的 setTimeout 变量中的函数
- nodejs-settimeout是否在不同的循环中共享变量
- toString似乎导致setTimeout不总是为toString的变量参数执行函数
- 可以't获取具有“t”的对象变量;这个“;由setTimeout()函数调用的对象函数中的属性
- 变量在Javascript中是如何工作的?可以在setTimeout期间更改变量值
- Javascript setTimeout作用域引用了错误的变量
- 一旦超时执行,清除或重新分配分配给 setTimeout 返回值的变量是否有任何技术点
- 使用变量作为 setInterval / setTimeout 中的时间
- 如何将变量传递到 setTimeout 函数中
- 为什么这个全局计数器变量不适用于 setTimeout
- JavaScript setTimeout可以't访问函数变量
- 如何在setTimeout中维护循环变量的值?Javascript
- Angular2,视图在settimeout变量更改后未更新
- 将对象内的变量传递到setTimeout
- javascript setTimeout()输出另存为变量
- for循环中的setTimeout,变量不变
- setTimeout似乎正在更改我的变量!为什么?
- setTimeout给了我新的变量,而不是旧的
- 如何从iframe(Javascript)中撤销setTimeout变量