let 和 var 在 for迴圈中的結果差異

Randy Chen
Randy Chen
Published in
3 min readSep 20, 2020
完全就是當我看到用var宣告在for迴圈判斷式的index,所展現的結果表情

這邊要先記錄一下,最近學到的用var 和用let來宣告for迴圈的index,造成不同的結果。

如果,原本是用C語言在寫的人,初次看到用var宣告for迴圈的index,所呈現的結果,應該是會嚇到不行XDD,因為,對C語言來說for迴圈判斷句中的index就是一個區域變數,並不需要換另一種宣告方式,才能將這個index宣告成區域變數,但在JavaScript中需要換成let宣告才能達成index是區域變數這種效果!!

所以,很值得記錄一下它們之間的差異

  1. 用var 宣告for迴圈的index變數

var 在宣告時是屬於一個函式作用域(function space),這是什麼意思呢?簡單來講就是它的作用域主要限制於函式中,若不是在函式內宣告則會被當作全域宣告

for(var i=0; i<3; i++)
{
setTimeout(function(){
console.log('這是第'+i+'次')
}, 3000);
}

最終呈現的結果會印出3次 "這是第3次",這很驚人,不是應該是”這是第0次”、”這是第1次”、”這是第2次” 嗎?!!

以下描述一下整個案發的經過

當JavaScript在執行for迴圈時,碰到setTimeout時,因為setTimeout是一個非同步的函式,所以,編譯器不會馬上執行它,會直接跳過它,繼續累加i。

而因為for迴圈的index i是用var宣告的,且我們並不是在函式內部宣告i,所以,也算是全域宣告,導致i累加的結果會被保留下來。

等到i被累加到3時,因為,它不小於3故跳出迴圈,此時,編譯器就會去執行setTimeout,而此時i被累加到3了,所以,會出現3次 ”這是第3次” 的錯誤結果。

2. 用let宣告for迴圈的index變數

let 的宣告方式則是區域作用域(block space),意思是依照程式碼的語句區塊為一個分界點當作作用域,最簡單辨別方式就是花括號「{ }」內

for(let i=0; i<3; i++)
{
setTimeout(function(){
console.log('這是第'+i+''次)
}, 3000);
}

寫法就只有差在用let去宣告i而已,但是,這次的結果就會如我們預期的執行 ”這是第0次”、”這是第1次”、”這是第2次” 的結果。

會有這種的結果就是因為,index i 不再是全域變數了,而是區域變數,故每次setTimeout都能綁定到相對應的i值,所以,執行的結果才會是對。

--

--

Randy Chen
Randy Chen

Keep fertilizing it, Keep watering it, Keep marching on