JavaScript ES6 的 let、const、var 有什麼差別

經過一個月的時間,JavaScript 學徒的試煉終於也要邁向終點了!
在結束之前,有些 ES 6 之中像是 let 與 const 等等的重要觀念,就寫篇筆記記錄一下吧!

過去常用的 var、window

之前寫 JS 總是用 var 宣告變數,但使用 var 宣告的變數,會汙染全域變數!

舉例:

1
2
3
4
5
var a = 1;
console.log(a);
for (var i = 0; i < 3; i++) {
console.log(i);
}

以「開發人員工具」輸入 “window” 去搜尋,會發現最上方出現 a 這個全域變數。而為了不汙染全域變數,我們有了 ES 6 這個很棒的寫法!

ES 6 優缺點概述

  • 優點
    • 解決 ES 5 的 BUG 與不便之處
    • 盡量避免汙染全域變數 - 維護性較高、不會污染其他開發者
  • 小問題
    • 舊版瀏覽器之問題 - 使用 Babel + Gulp 可解決

ES 6 - let 的特性

  • let 與 const 用來宣告區塊裡的變數,即「區域變數」。
    • 所謂的 “區塊” 就是指這個 { 大括號 } 裡面的東西。

舉例:

1
2
3
4
5
6
7
8
var a = 0; // 全域變數
function changeA() {
let a = 0; // 區域變數
a = 1;
console.log(a); // 1
}
changeA();
console.log(a); // 0

結果:1、0
因為第一個 function changeA(){…} 裡面的 a “只會” 存活在那個區塊 { } 裡面!
所以 function 裡面的 a = 1 並沒有變更到外面的 a ,因此第二個 console.log(a) 就會回傳 0。

註:ES 6 建議 JS 都寫成 “函數式”
盡量以函式呼叫的方式去做設計,不要使用到 var

let 的 for 用法

此為 JS 課程中的例題:

<– HTML –>

1
2
3
4
5
<ul class="list">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>

<– JS –>

1
2
3
4
5
6
7
8
const listLen = document.querySelectorAll('.list li').length;
for (var i = 0; i < listLen; i++) {
document
.querySelectorAll('.list li')
[i].addEventListener('click', function () {
alert(i + 1);
});
}

我們想要讓上面的 li 被點擊時,跳出 alert 通知點到哪個 li,因此監聽 li 並加上 click 事件。

然而結果卻不如預期,我們發現不管點擊哪個 li 彈跳出來的都是 4!

這是因為被全域變數所影響,for 迴圈跑完之後 i 的值已經等於 i++ 完的結果,汙染了全域變數。

改善方式

<– JS –>

1
2
3
4
5
6
7
8
const listLen = document.querySelectorAll('.list li').length;
for (let i = 0; i < listLen; i++) {
document
.querySelectorAll('.list li')
[i].addEventListener('click', function () {
alert(i + 1); // 用 let 的話,會在大括號區塊內重新綁定
});
}

重點在 for(var i=0; i<listLen; i++){ }

注意右邊的大括號,let 的功能就是在 for 執行每一次時,裡面的 i 都可以存活在個別的大括號 “作用域” 裡面,彼此執行的內容就不用像是全域變數一樣個別干擾哩!

感覺就像是 …
let i = 0 時,i 存活在 i 為 0 的 { } 作用域裡面,執行 function (){ alert(i+1)},變成 alert(1)。
let i = 1 時,i 存活在 i 為 1 的 { } 作用域裡面,執行 function (){ alert(i+1)},變成 alert(2)。

ES 6 - const 的特性

  • 唯讀變數 - 不能去做修改
  • 用在一些不能被變更的變數 - 例如 url 網址
  • 例外 : { 物件 } 跟 [ 陣列 ] 還是會被變更
    • 可以用 freeze() 方法
1
2
3
4
5
6
const obj = {
url: 'https://xx.com',
};
Object.freeze(obj); // 使用 freeze 就不能修正了
obj.url = '30';
console.log(obj.url); // 30 -> https://xx.com

好處:有時候,有些預設的東西不想被干擾或更改,就可以使用 const 與 freeze (物件或陣列) 的特性囉!

let 與 const 的注意事項

1. 向上提升

1
2
3
4
// var a; // 就相當於有這一行存在
console.log(a); // undefined
var a = 3;
console.log(a); // 3

Q:為何第一次 console.log(a) 是顯示 undefined,而不是顯示找不到 a 呢?
A:因為 JS 編譯預設 var 會向上提升,建立變數或 function 時,都會自動提升到最上面去。

1
2
3
4
console.log(a); // 抓不到值
let a = 3;
// const a = 3;
console.log(a); // 3

若將 var 改為 let a = 3; 就會抓不到值囉!

var 有向上提升的特性,let 跟 const 沒有。

2. 在同個區塊 { } 上不能重複命名

var 可以重新賦予其值

1
2
var a = 1;
var a = 2; // var 可以重新賦予

let 跟 const 不能重新賦予

1
2
3
4
let a = 1;
let a = 2; // a 已被賦予值
const b = 1;
const b = 2; // b 已被賦予值

3. const 跟 let 不會在全域變數 (window) 裡面

1
2
3
let a = 1;
const b = 1;
var c = 1;

a 跟 b 不會出現在 window 裡,c 則會出現在 window 裡,因為 c 是全域變數。

以上資源是我自己整理過後的筆記,若有錯誤歡迎隨時和我聯繫。