前端三十|08. [JS] 請寫出間隔一秒印出 1, 2, 3, 4, 5 的程式碼。
Published in
8 min readSep 24, 2019
相信稍有經驗的開發者多少都看過這題了,應該是彈指之間便能輕鬆解決;但初步接觸 JavaScript 的朋友,可能會撰寫出類似下面範例的程式碼:
for(var i = 1; i <= 5; i++) {
setTimeout(function() {
console.log(i)
}, 1000 * i)
}
然後就得到間隔一秒印出五次 6
的結果。
為什麼會這樣呢?今天就讓我們研究這現象背後的原因吧~
本系列文已經重新編校彙整編輯成冊,並正式出版囉!
《前端三十:從 HTML 到瀏覽器渲染的前端開發者必備心法》好評販售中!
喜歡我文章內容的讀者們,歡迎您前往購買支持!
拆解問題
我們先把題目拆分簡化,先把傳入的回呼函式(Callback Function)遮掉的話,就只剩這樣:
for(var i = 1; i <= 5; i++) {
setTimeout(/* callback */, 1000 * i)
}
可以明確看出這段程式碼,執行了五次 setTimeout
,而 setTimeout
這個函式傳入了兩個參數,一個是我們暫時不看的回呼函式,另一個則是等待時間,分別在第 1, 2, 3, 4, 5 秒時執行回呼函式。
接著看回呼函示的內容:
function() {
console.log(i)
}
就只是單純的印出 i
,但印的不是執行 setTimeout
時的 i
,而是執行 console.log(i)
時的 i
;當迴圈跑完時, i
的值會停在 6
(迴圈的中止條件),屆時才執行的 console.log(i)
當然印的就會是 6
。
一定有人想到了,那如果題目沒有要求間隔一秒,把 setTimeout
的等待時間改成 0
呢?
for(var i = 1; i <= 5; i++) {
setTimeout(function() {
console.log(i)
}, 0)
}
// 6, 6, 6, 6, 6