let
let 定義常量
const
const 定義變數
為什麼不使用var
最簡單的答案就是let提供塊作用域(block-scoping),這會比var提供的以函式為作用域有更加精細化的控制。
如下一個例子:
問題: 在下面的例子中,請說出控制檯的列印結果。
var callbacks = [];
(function() {
for (var i = 0; i < 5; i++) {
callbacks.push( function() { return i; } );
}
})();
console.log(callbacks.map( function(cb) { return cb(); } ));
我們將for迴圈執行五次,每次將一個函式push到callbacks
陣列中。最後callbacks
陣列裡面的每一個函式的執行結果列印出來。
一個新手工程師經過深思熟慮可能會回答[0, 1 , 2, 3, 4]
, 然而卻掉入了JavaScript
的”hoisting陷阱”。
只有當你理解了hoisting, 才能給出正確的答案[5, 5, 5, 5, 5]
。
var callbacks = [];
(function() {
var i;
for (i = 0; i < 5; i++) {
callbacks.push( function() { return i; } );
}
})();
console.log(callbacks.map( function(cb) { return cb(); } ));
注意上面的程式碼,JavaScript
將變數提升到函式定義的頂部,經過整個for
迴圈,callbacks
裡面儲存的5個函式指向的同一個變數i
的值已經是5。所以最終列印出來的值都為5。
在以前要通過各種奇淫技巧來解決這個問題,併成功返回[0, 1, 2, 3, 4]
, 現在我們有了let
,就可以很簡單解決問題:
var callbacks = [];
(function() {
for (let i = 0; i < 5; i++) {
callbacks.push( function() { return i; } );
}
})();
console.log(callbacks.map( function(cb) { return cb(); } ));
因為let
擁有塊作用域,所以使用let
宣告的變數i
不會被提升到函式頂部,i
的作用域在for
迴圈, 就會每次迴圈有獨立的值。
那我們是不是應該不要使用var
了呢?如果你想要一個變數擁有函式作用域,var
還是很有用的。
本作品採用《CC 協議》,轉載必須註明作者和本文連結