es6學習之路(2):作用域,不存在變數提升,避免暫時性死區,與全域性物件的屬性脫鉤
阿新 • • 發佈:2019-02-14
1、ES6 新增了let命令,用來宣告變數。它的用法類似於var.
const宣告一個只讀的常量。一旦宣告,常量的值就不能改變.const宣告的變數不得改變值,這意味著, const 一旦宣告變數,就必須立即初始化,不能留到以後賦值。
這2個都是在所在的程式碼塊內有效。意味著他們有自己的作用域。而且,不存在變數,所以存在“暫時性死區”的問題。
ES6 明確規定,如果區塊中存在let和const命令,這個區塊對這些命令宣告的變數,從一開始就形成了封閉作用域。凡是在宣告之前就使用這些變
量,就會報錯。
總之,在程式碼塊內,使用 let 命令宣告變數之前,該變數都是不可用的。這在語法上,稱為 “ 暫時性死區 ” ( temporal dead zone ,簡稱 TDZ )
下面的程式碼如果使用var,最後輸出的是 10 。 var a = []; for (var i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 10 如果使用let,宣告的變數僅在塊級作用域內有效,最後輸出的是 6 。 var a = []; for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 6 console.log(foo); // 輸出 undefined console.log(bar); // 報錯 ReferenceError var foo = 2; let bar = 2;
2、未宣告的全域性變數,自動成為全域性物件window的屬性,這被認為是 JavaScript 語言最大的設計敗筆之一。這樣的設計帶來了兩個很大的問題,首先是沒
法在編譯時就報出變數未宣告的錯誤,只有執行時才能知道,其次程式設計師很容易不知不覺地就建立了全域性變數(比如打字出錯)。另一方面,從語義
上講,語言的頂層物件是一個有實體含義的物件,也是不合適的。
ES6 為了改變這一點,一方面規定,為了保持相容性,var命令和function命令宣告的全域性變數,依舊是全域性物件的屬性;另一方面規定,let命
令、const命令、class命令宣告的全域性變數,不屬於全域性物件的屬性。也就是說,從 ES6 開始,全域性變數將逐步與全域性物件的屬性脫鉤。
var a = 1;
// 如果在 Node 的 REPL 環境,可以寫成 global.a
// 或者採用通用方法,寫成 this.a
window.a // 1
let b = 1;
window.b // undefined
上面程式碼中,全域性變數a由var命令宣告,所以它是全域性物件的屬性;全域性變數b由let命令宣告,所以它不是全域性物件的屬性,返回undefined。