{ let a = 10; var b = 1; } a // ReferenceError: a is not defined b // 1
for 迴圈的計數器,就很適合使用 let 命令。
for (let i = 0; i < 10; i++) { // ... } console.log(i); // ReferenceError: i is not defined
上面程式碼中,計數器 i 只在 for 迴圈體內有效,在迴圈體外引用就會報錯。
下面的程式碼如果使用 var,最後輸出的是 10。
var a = []; for (var i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 10
上面程式碼中,變數i
是var
命令宣告的,在全域性範圍內都有效,所以全域性只有一個變數i
。每一次迴圈,變數i
的值都會發生改變,而迴圈內被賦給陣列a
的函式內部的console.log(i)
,裡面的i
指向的就是全域性的i
。也就是說,所有陣列a
的成員裡面的i
,指向的都是同一個i
,導致執行時輸出的是最後一輪的i
的值,也就是 10。
如果使用let
,宣告的變數僅在塊級作用域內有效,最後輸出的是 6。
var a = []; for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 6
上面程式碼中,變數i
是let
宣告的,當前的i
只在本輪迴圈有效,所以每一次迴圈的i
其實都是一個新的變數,所以最後輸出的是6
。你可能會問,如果每一輪迴圈的變數i
都是重新宣告的,那它怎麼知道上一輪迴圈的值,從而計算出本輪迴圈的值?這是因為 JavaScript 引擎內部會記住上一輪迴圈的值,初始化本輪的變數i
時,就在上一輪迴圈的基礎上進行計算。
另外,for
迴圈還有一個特別之處,就是設定迴圈變數的那部分是一個父作用域,而迴圈體內部是一個單獨的子作用域。
for (let i = 0; i < 3; i++) { let i = 'abc'; console.log(i); } // abc // abc // abc