這是我在segmentfault上看到的一個(gè)問(wèn)題蜈抓。原問(wèn)題鏈接
for (var i = 1; i <= 5; i++) {
setTimeout(function timer() {
console.log(i);
}, i * 1000);
}
問(wèn)題
其實(shí)我們想得到的結(jié)果是1婴栽,2,3爱谁,4晒喷,5,結(jié)果卻是五個(gè)6
執(zhí)行結(jié)果
每隔1秒 輸出 i 為6
原因
輸出i 為什么為6
JS處理時(shí)用的是隊(duì)列访敌,所以在for循環(huán)里只是把每個(gè)setTimeout任務(wù)添加到隊(duì)列里凉敲,等f(wàn)or循環(huán)執(zhí)行完之后,再去執(zhí)行setTimeout函數(shù)寺旺,而此時(shí)的i變成了6荡陷,所以i輸出為6,這是i 為6的理解
為什么會(huì)每隔一秒執(zhí)行
剛進(jìn)入for循環(huán)的時(shí)候迅涮,i為1,所以相對(duì)于現(xiàn)在延遲一秒將timer函數(shù)添加到隊(duì)列當(dāng)中废赞,然后for循環(huán)還要繼續(xù)啊,并沒(méi)有等一秒再繼續(xù)循環(huán)啊叮姑,然后進(jìn)行第二次循環(huán)唉地,這時(shí)候i為2,所以相對(duì)于現(xiàn)在延遲兩秒將timer函數(shù)送進(jìn)隊(duì)列。以此類(lèi)推传透。for循環(huán)的時(shí)間忽略不計(jì)的話耘沼,timer函數(shù)就以每秒一次的頻率執(zhí)行啦。
解決辦法
- 辦法1
for (var i = 1; i <= 5; i++) {
(function(j) {
setTimeout(function timer() {
console.log(j);
}, j * 1000);
})(i);
//用閉包來(lái)解決:通過(guò)一個(gè)立即執(zhí)行函數(shù)朱盐,為每次循環(huán)創(chuàng)建一個(gè)單獨(dú)的作用域
- 辦法2
//把var 改為let群嗤,let 每次都會(huì)創(chuàng)建一個(gè)塊級(jí)作用域
for (let i = 1; i <= 5; i++) {
setTimeout(function timer() {
console.log(i);
}, i * 1000);
}
- 辦法3
//類(lèi)似于方法二,使用setTimeout的第三個(gè)參數(shù)直接傳參
for (var i = 1; i <= 5; i++) {
setTimeout(function(i) {
console.log(i);
}, i * 1000,i);
}
辦法1用閉包解決兵琳,辦法2用作用域解決狂秘,辦法三不常見(jiàn),但使用的是setTimeout的第三個(gè)參數(shù)直接傳參躯肌,對(duì)第三個(gè)參數(shù)不了解的看這里
每天都努力一點(diǎn)點(diǎn)
謝謝你看完