let const 和 var的區別
作用域
ES5 中的作用域有:全局作用域、函數作用域,ES6 中新增了塊級作用域。塊作用域由 { } 包括,if 語句和 for 語句里面的 { } 也屬于塊作用域。
var關鍵字
- 沒有塊級作用域的概念
// global scope
{var a = 10;
}
console.log(a); // 10
在全局中輸出a為10說明var不存在塊級作用域的概念
-
有全局作用域,函數作用域的概念
var b = 20; function test() {var a = 10;console.log(a);console.log(b); } test(); console.log(a); // 10 20 a is not defined
-
不初始化值默認為 undefined,存在變量提升
console.log(a); //undefined var a; a = 10;
-
全局作用域用 var 聲明的變量會掛載到 window 對象下
//Global Scope
var a = 10;
console.log(a); //10
console.log(window.a); //10
console.log(this.a); //10
- 同一作用域中允許重復聲明
//Global Scope
var a = 10;
var a = 20;
console.log(a); //20checkscope();
function checkscope(){//Local Scopevar b = 10;var b = 20;console.log(b); //20
}
上面代碼中,在 Global Scope 中聲明了 2 次 a,以最后一次聲明有效,打印為 20。同理,在 Local Scope 也是一樣的。
let 關鍵字
- 有塊級作用域的概念
{//Block Scopelet a = 10;
}
console.log(a); //ReferenceError: a is not defined
上面代碼中,打印 a 報錯,說明存在 Block Scope 的概念。
- 不存在變量提升(不可以在聲明之前使用)
{//Block Scopeconsole.log(a); //ReferenceError: Cannot access 'a' before initializationlet a = 10;
}
上面代碼中,打印 a 報錯:無法在初始化之前訪問。說明不存在變量提升。
- 暫時性死區
{//Block Scopeconsole.log(a); //ReferenceError: Cannot access 'a' before initializationlet a = 20;
}if (true) {//TDZ開始console.log(a); //ReferenceError: Cannot access 'a' before initializationlet a; //TDZ結束console.log(a); //undefineda = 123;console.log(a); //123
}
上面代碼中,使用 let 聲明的變量 a,導致綁定這個塊級作用域,所以在 let 聲明變量前,打印的變量 a 報錯。
這是因為使用 let/const 所聲明的變量會存在暫時性死區。
什么叫做暫時性死區域呢?翻譯成人話就是:
當程序的控制流程在新的作用域(module、function 或 block 作用域)進行實例化時,在此作用域中用 let/const 聲明的變量會先在作用域中被創建出來,但因此時還未進行詞法綁定,所以是不能被訪問的,如果訪問就會拋出錯誤。因此,在這運行流程進入作用域創建變量,到變量可以被訪問之間的這一段時間,就稱之為暫時死區。
再簡單理解就是:
ES6 規定,let/const 命令會使區塊形成封閉的作用域。若在聲明之前使用變量,就會報錯。
總之,在代碼塊內,使用 let/const 命令聲明變量之前,該變量都是不可用的。
這在語法上,稱為 “暫時性死區”( temporal dead zone,簡稱 TDZ)。
其實上面不存在變量提升的例子中,其實也是暫時性死區,因為它有暫時性死區的概念,所以它壓根就不存在變量提升了。
- 同一塊作用域中不允許重復聲明
{//Block Scopelet A;var A; //SyntaxError: Identifier 'A' has already been declared
}
{//Block Scopevar A;let A; //SyntaxError: Identifier 'A' has already been declared
}
{//Block Scopelet A;let A; //SyntaxError: Identifier 'A' has already been declared
}
const 關鍵字
- 必須立即初始化,不能留到以后賦值
// Block Scope
const a; // SyntaxError: Missing initializer in const declaration }
上面代碼中,用 const 聲明的變量 a 沒有進行初始化,所以報錯。
- 常量的值不能改變
//Block Scope
{const a = 10; a = 20; // TypeError: Assignment to constant variable
}
上面代碼中,用 const 聲明了變量 a 且初始化為 10,然后試圖修改 a 的值,報錯。
const 實際上保證的,并不是變量的值不得改動,而是變量指向的那個內存地址所保存的數據不得改動。