1.let塊級做用域javascript
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。java
若是使用let
,聲明的變量僅在塊級做用域內有效,最後輸出的是 6。數組
var a = []; for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 6
for (let i = 0; i < 3; i++) { let i = 'abc'; console.log(i); }
console.log(i);
計數器只在循環體內有效,在循環體外引用就會報錯。
循環還有一個特別之處,就是設置循環變量的那部分是一個父做用域,而循環體內部是一個單獨的子做用域。
iforfor
let 函數
console.log(foo); // 輸出undefined var foo = 2; // let 的狀況 console.log(bar); // 報錯ReferenceError let bar = 2;
暫時性死區:ES6 明確規定,若是區塊中存在let
和const
命令,這個區塊對這些命令聲明的變量,從一開始就造成了封閉做用域。凡是在聲明以前就使用這些變量,就會報錯。spa
if (true) { // TDZ開始 tmp = 'abc'; // ReferenceError console.log(tmp); // ReferenceError let tmp; // TDZ結束 console.log(tmp); // undefined tmp = 123; console.log(tmp); // 123 }
ES6 規定暫時性死區和let
、const
語句不出現變量提高,主要是爲了減小運行時錯誤,防止在變量聲明前就使用這個變量,從而致使意料以外的行爲。這樣的錯誤在 ES5 是很常見的,如今有了這種規定,避免此類錯誤就很容易了。code
總之,暫時性死區的本質就是,只要一進入當前做用域,所要使用的變量就已經存在了,可是不可獲取,只有等到聲明變量的那一行代碼出現,才能夠獲取和使用該變量。blog
爲何須要塊級做用域或者es變量的優點:let
實際上爲 JavaScript 新增了塊級做用域。ES5 只有全局做用域和函數做用域,沒有塊級做用域,這帶來不少不合理的場景。token
第一種場景,內層變量可能會覆蓋外層變量。由於let不容許重複定義,不會出現這個問題ip
第二種場景,用來計數的循環變量泄露爲全局變量。let是塊級做用域,不會成爲全局變量作用域