[英]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.