前端三十|08. [JS] 請寫出間隔一秒印出 1, 2, 3, 4, 5 的程式碼。

Schaos
Schaos’s Blog
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

--

--