EP.26 RE:從零開始的學習 JS 生活-第二十六日之 ES6 變數

前言

轉生第二十六日,這一篇開始將會介紹 ES6,首先是 ES6 的 let & const

let & const

首先什麼是 let & const 呢?一般來講我們在宣告變數的時候是使用 var 來建立變數,後來 ES6 加入了兩個新的變數宣告方式,這個變數宣告方式其實可以改善很多開發上的 bug,基本上 let & const 我們可以這樣子了解

  • let - 變數與原本的 var 雷同
  • const - 常數,意旨不能變動的值

基本上你在開發時,若對於 let & const 不清楚,可以嘗試先把原本的 var 修改成 let,等到後面熟悉了 let & const 這兩者差異,再來去做調整,所以假設原本的寫法是這樣:

1
2
var a = 1;
console.log(a);

此時你可以先修改成這樣:

1
2
let a = 1;
console.log(a);

這兩者差異並不大。

let

首先前面有講到 letvar 差異性不大,那這時候你可能會說 「差異不大那為何要改用 let?」,原本我們使用 var 來建立變數,是會發生一些問題出現問題出現:

1
2
3
4
5
var a = 1;
if(true) {
var a = 2;
}
console.log(a);

我們會發現全域變數 a 被修改成 2 了 ↓

2

而這就是所謂的變數汙染,那 let 呢?讓我們改寫上面範例:

1
2
3
4
5
let a = 1;
if(true) {
let a = 2;
}
console.log(a);

你會發現 a 還是 1,並沒有受到內層的 let a = 2 影響而改變 ↓

1

所以我們可以得到一個結論 let 是一個區域 (block) 變數,區域 (block) 的意思是指花括號({ })裡面的區塊,所以使用 let 的變數就只會存活於花括號內,而 var 呢? var 是函式 (function) 變數,函式 (function) 的意思,就是它的範圍只會在 function 內,但是其實正確來講應該是這樣解釋會比較好 let 是一個 block 作用域變數,而 var 是一個 function 作用域變數。

const

const 呢?先講講什麼是常數,常數又稱之為定數,就是在指固定不變的值,以往我們在宣告變數的時候是可以一直重複修改的:

1
2
3
var a = 1;
a = 2;
a = 3;

通常這種變數宣告方式是有可能發生不小心覆蓋不想覆蓋的變數值,所以此時如果你的變數值是固定的,並且不會變動,那麼就可以使用 const,如果我們一但使用 const 宣告變數後卻還變更它呢?

1
2
const a = 1;
a = 2;

此時你會出現一個錯誤訊息,也就是 Assignment to constant variable.,簡單來講它是在跟你講說「我不給你修改這個常數」 ↓

Assignment to constant variable.

但是這邊最後有一個東西要注意,若你在宣告變數時,若 let a; 這樣是不會出現錯誤的,可是 const 是必須給予值的,若你沒有賦予初始值,那麼就會得到一個錯誤 ↓

Missing initializer in const declaration

簡單來講就是 「你忘記替我賦值了」。

補充

最後稍微講一下 let & const 的 Hoisting,前面我們已經了解了 Hoisting 的部分,但是在 ES6 的 let & const 呢?它有 Hoisting 嗎?其實 let & const 沒有 Hoisting 而是另一種說法稱之為暫時性死區,這是什麼意思呢?讓我們看一下程式碼:

1
2
console.log(a);
let a = 1;

正常來講你應該會得到一個 undefined,但是當你使用 ES6 變數宣告則會得到 Uncaught ReferenceError: Cannot access 'a' before initialization

Uncaught ReferenceError: Cannot access 'a' before initialization

這是什麼意思呢?簡單來講就是「我還沒執行這一段之前你不能使用這個變數」,在 MDN 文件中也有說明 let & const 並沒有所謂的 Hoisting,而是有所謂的暫時性死區,以下截取 MDN 部分文件內容 ↓

In ECMAScript 2015, let bindings are not subject to Variable Hoisting, which means that let declarations do not move to the top of the current execution context. Referencing the variable in the block before the initialization results in a ReferenceError (contrary to a variable declared with var, which will just have the undefined value). The variable is in a “temporal dead zone” from the start of the block until the initialization is processed.

原文位置

這一篇原文是只有講 let,但其實 const 也是一樣的,所以當你實際操作也會得到一樣結果 ↓

Uncaught ReferenceError: Cannot access 'a' before initialization

結尾

下一篇的 RE:從零開始的學習 JS 生活-第二十七日 將會介紹 ES6 箭頭函式。