在 ES5 中,咱們一般會使用 var
來聲明變量。在使用 var
聲明變量的時候,一般會遇到變量聲明提高的問題。這種機制會讓不少初學者迷惑不解。其實當咱們理解了一個變量一般包括聲明和賦值兩個部分,這個問題也就不難理解了。編程
// 1
console.log(a); // undefined
var a = 3;
// 2
function foo() {
console.log(b); // undefined
if (true) {
var b = 2;
}
}
複製代碼
事實上,不管在全局做用域或者函數做用域中,只要經過 var
關鍵字聲明的變量,不論在哪裏聲明,都會被當成在當前做用域頂部聲明的變量。bash
// 1
var a;
console.log(a);
a = 3;
// 2
function foo() {
var b;
console.log(b);
if (true) {
b = 2;
}
}
複製代碼
其實,變量提高的機制,不太符合咱們的編碼習慣,咱們經常但願代碼可以按照順序執行,這也符合通常人的邏輯習慣。爲此 ES6 引入了塊級做用域的概念。微信
塊級做用域其實就是詞法做用域,咱們的代碼寫在哪,就會在哪裏執行,這更符合咱們的編程習慣。咱們常說的塊包括函數內部 和 {}之間的部分。函數
爲了實現塊級做用域,ES6 採用 let
和 const
代替 var
來聲明變量。用 let
和 const
聲明的變量會把變量的做用域限制在當前的代碼塊中,而且聲明的變量不會被提高。另外,用 let
聲明的變量,在同一代碼塊內,禁止重複聲明。ui
// 一、變量不會提高
console.log(a); // ReferenceError: a is not defined
let a = 3;
// 二、變量只能在當前做用域訪問
if (true) {
const b = 3;
console.log(b); // 3
}
console.log(b); // ReferenceError: b is not defined
// 三、禁止重複聲明
function foo() {
let c = 3;
let c = 4; // Identifier 'c' has already been declared
}
foo();
複製代碼
用 let
和 const
均可以建立一個塊級做用域,惟一的區別是 const
用來聲明一個常量,它的值一旦被設定後不可修改。因此,用 const
聲明的常量必須初始化。編碼
// 一、不可更改
const a = 1;
a = 2; // TypeError: Assignment to constant variable.
// 二、必須初始化
const b; // SyntaxError: Missing initializer in const declaration
複製代碼
關於 const
聲明的變量不可修改,有一個值得注意的地方就是用 const
聲明一個對象。好比:spa
const tom = {
age: 18,
city: 'shanghai'
};
tom.age = 19; // 這是能夠的
複製代碼
咱們能夠理解爲,用 const
聲明瞭一個變量 tom,將一個對象的引用地址賦值給變量 tom,只要這個引用地址不發生變化,內部的值是能夠修改的。code
在 ES5 中,比較讓人頭疼的地方可能就是 for 循環了。在循環中,咱們用 var
聲明一個變量,循環結束後,咱們實際上是但願這個變量被銷燬的。但因爲 var
聲明的變量具備聲明提高的特性,因此當咱們用 for 循環的時候,每每會污染咱們的全局做用域。cdn
for (var i = 0; i < 10; i++) {
// do something
}
console.log(i); // 10
// 當循環結束的時候,其實咱們是但願變量 i 能夠被銷燬的。
// 但其實它被留在了全局
複製代碼
這個時候,咱們使用 let
來聲明循環中的變量,就能夠輕易的解決這個問題。對象
for (let i = 0; i < 10; i++) {
// do something
}
console.log(i); // ReferenceError: i is not defined
// 能夠看到,循環結束,變量 i 就被銷燬了。 perfect~~
複製代碼
最後總結一下,let
和 const
幫助咱們解決了很多問題,咱們不會再爲變量提高引起的種種問題而困惑了,同時在循環中使用 let
來代替 var
能夠在循環結束的時候銷燬變量,避免無用的變量影響全局。而當前使用塊級綁定的最佳實踐是:默認使用 const
,只在肯定須要改變變量的值時,使用 let
,以最大化地避免錯誤的產生。
若是文章中有錯誤或表述不嚴謹的地方,歡迎指正。
也歡迎你們關注個人同名微信公衆號:李等等扣丁