參考資料:《JavaScript高級程序設計》
在 let 出現之前,for 循環定義的迭代變量會滲透到循環體外部:
for (var i = 0; i < 5; ++i) {
// 循環邏輯
}
console.log(i); // 5
改成使用 let 之后,這個問題就消失了,因為迭代變量的作用域僅限於 for 循環塊內部:
for (let i = 0; i < 5; ++i) {
// 循環邏輯
}
console.log(i); // ReferenceError: i 沒有定義
在使用 var 的時候,最常見的問題就是對迭代變量的奇特聲明和修改:
for (var i = 0; i < 5; ++i) {
setTimeout(() => console.log(i), 0)
}
// 你可能以為會輸出 0、1、2、3、4
// 實際上會輸出 5、5、5、5、5
之所以會這樣,是因為在退出循環時,迭代變量保存的是導致循環退出的值:5。
在之后執行超時邏輯時,所有的 i 都是同一個變量,因而輸出的都是同一個最終值。
而在使用 let 聲明迭代變量時,JavaScript 引擎在后台會為每個迭代循環聲明一個新的迭代變量。
每個 setTimeout 引用的都是不同的變量實例,所以 console.log 輸出的是我們期望的值,也就是循
環執行過程中每個迭代變量的值。
for (let i = 0; i < 5; ++i) {
setTimeout(() => console.log(i), 0)
}
// 會輸出 0、1、2、3、4
這種每次迭代聲明一個獨立變量實例的行為適用於所有風格的 for 循環,包括 for-in 和 for-of
循環。