let容許你聲明一個做用域被限制在塊級中的變量、語句或者表達式。與var關鍵字不一樣的是,它聲明的變量只能是全局或者整個函數塊的。javascript
let聲明的變量只能在其聲明的塊或子塊中使用,這個和var很類似,兩者之間最主要的區別在於var聲明的變量的做用域是整個封閉函數。java
// var function testVar() { var a = 0; if (true) { var a = 1; console.log(a); // 輸出1 } console.log(a); // 輸出1 } // let function testLet() { let a = 0; if (true) { let a = 1; console.log(a); // 輸出1 (不一樣的變量) } console.log(a); // 輸出0 }
在testVar函數裏面重複輸出了1,var聲明的變量的做用域是整個封閉函數,因此到if裏面被賦值爲1,最後都輸出爲1。es6
在testLet函數裏面{},兩個花括號至關於一個做用域,兩個a在不一樣的做用域裏面,因此不受影響。(使用let能夠徹底代替閉包)閉包
好比給許多函數添加事件函數
/* * 使用let */ let lists = document.getElementsByTagName('li'); for (let i = 0; i < lists.length; i++) { lists[i].onclick = function(ev) { console.log(`點擊了第${i}個元素`); } } console.log(i); // 報錯 Uncaught ReferenceError: i is not defined
運行這段代碼點擊每一個元素都能輸出正確的i值,並且console報錯code
var lists = document.getElementsByTagName('li'); for (var i = 0; i < lists.length; i++) { lists[i].onclick = function(ev) { console.log("點擊了第"+i+"個元素"); // 點擊了第6個元素 } } console.log(i); // 輸出6 // 解決辦法,可使用自執行函數 var lists = document.getElementsByTagName('li'); for (var i = 0; i < lists.length; i++) { (function(i){ lists[i].onclick = function(ev) { console.log("點擊了第"+i+"個元素"); // 正常輸出 } })(i); } console.log(i); // 輸出6
上面的代碼能夠看出不管點擊哪一個元素都是輸出「點擊了第6個元素」,並且最後console也是6。事件
由於(匿名)內部函數的五個實例引用了變量i的五個不一樣實例。注意,若是你將let替換爲var,則它將沒法正常工做,由於全部內部函數都將返回相同的i:6的最終值。此外,咱們能夠經過將建立新元素的代碼移動到每一個循環的做用域來保持循環更清晰。ip
不能再相同函數和相同做用域裏面從新聲明同一個變量作用域
{ let a; let a; //Uncaught SyntaxError: Identifier 'a' has already been declared }
let 綁定不受變量提高的約束,也就是let聲明不會被提高到當前執行上下文的頂部,若是你在初始化以前引用它,也會報上面那個錯誤。get
{ console.log(a); // Uncaught ReferenceError: a is not defined let a; let b; }
上面介紹了es6做用域的問題,表達式(2 + 55)內的標識符「a」會解析爲if塊的a,而不是覆蓋值爲2的a。if塊的a已經生明,並未初始化,它仍處在暫存死區
function test(){ var a = 2; if (true) { let a = (a + 55); // ReferenceError } } test();
當在塊中使用時,let將變量的做用域限制爲該塊。注意var的做用域在它被聲明的函數內的區別。
--- 參考阮老師的 《ECMAScript 6 入門》