JS-ES6-let變數&const常數
ES6 新語法有很多,第一篇就以先前 JavaScript小學-variable變數 作延伸,介紹 let
、const
,為什麼不用 var
就好非要多了解新的語法呢?來看看吧~
為什麼不用 var 改用 let 、const ?
先來看看這兩個 let
和 const
:
let
跟var
差不多都是變數,代表值可以做替換const
宣告常數,代表不能在修改,一宣告就固定了
雖然看起來差不多,但是有一個很重要的點是存活範圍不同!!let
和 const
都是要用來宣告區塊 {}
中的變數意思就是只存活在 {}
中,而使用 var 的話,可能會污染到全域變數,何謂污染🥵?我們用一段 code 來看,包含了一個變數宣告,還有一個 for 迴圈:
var apple = 10
console.log(apple);
for(var i=0 ; i<3 ; i++){
console.log(i);
}
console.log(window);
下圖可以看到在 console 中,宣告的 apple
有在 window 中:
可能大家會覺得沒毛病啊,我就是要宣告全域變數,又沒關係,但繼續看下圖的 window 中也出現了 for迴圈 中的 i
,但是當初裡面的 i
只是要用來跑迴圈,不需要他當作一個全域變數,這時候是不是就污染到了!!!
而程式越來越多,可能就會不小心互相污染了💀💀💀,所以在 ES6 中才會有新的用法~
let 和 const 共同特性
- 不能重複宣告
let myName = "Jordan";
myName ="Peter";
console.log(myName);
let myName = "Zoe";
console.log(myName);//Identifier 'myName' has already been declared
第二次宣告後會產生 error,這其實有好處,因為以前使用 var
時,重複宣告也沒差,可能沒注意就被蓋過去,而 let
就會看到錯誤。
- 活在
{}
且階級分明,父層變數可以影響到子層,但是子層變數不能影響到父層:
function varMing () {
var ming = '小明';
if (true) {
var ming = '杰哥';
// 這裡的 ming 依然是外層的小明,所以小明即將被取代
}
console.log(ming); // '杰哥'
}function letMing () {
let ming = '小明';
if (true) {
let ming = '杰哥';
// 這裡的 ming 是不同的,只有在這個 if block 才有作用
}
console.log(ming); // '小明'
}function constMing () {
if (true) {
const ming = '杰哥';
// 這裡的 ming 只有在這個 if block 才有作用
}
console.log(ming); // error,找不到
}
varMing();
letMing();
constMing();
由上面可以看到 var 是存活在 function 中,只要同一個 function 中(函式作用域funciton scope),就是同一個,在宣告一次,就會覆蓋掉前一個。
而 let
呢? 是存活在 ()
中括弧 {}
大括號中的(區塊作用域block scop),即便在同一個 function 中,但是不同 {}
內重新宣告的話就不是同一個。let
和 const
在父層區塊也找不到子層區塊的變數。
當然同級的 function 也管不了,就如同一家公司的設計部經理和開發部經理怎麼能互相管部下:
if (true) {
let a = 'hiA';
console.log(b);//undefined
}
if (true) {
const b = 'hiB'
console.log(a);//undefined
}
- 在全域 宣告
let
變數時,不會像var
一樣掛在 window 這個物件上:
var girl = "Zoe";
console.log(window.girl);//var 會出現 "Zoe"let girl = "Zoe";
console.log(window.girl);//let 會出現 undefinedconst girl = "Zoe";
console.log(window.girl);//let 會出現 undefined
- 沒有 Hoisting 向上提升的功能
之前提到使用 var
宣告變數的時候具備向上提升的功能,所以其實在第一個 console.log()
之前已經先 var a;
,所以才會出現 undefinded。
console.log(a); //undefinded
var a = 1;
console.log(a); //1
但是如果是使用 let
、const
會出現 error,因為不會提前,所以其實沒有 a 這個變數😏
Const
const
和 let
雖然有很多共同特性,但 const
是宣告一個常數,簡單來說就是不可以再做修改的變數,以下面這個範例來說,小明如果使用 const 做宣告,那麼就無法再使用 let
、const
做調整了。因為 const
宣告變數主要是用來作唯讀(也就是不能變更的資料,例如: AJAX 的連結)。
const googleUrl = "<https://google.com.tw>";
googleUrl = "<https://yahoo.com.tw>";
console.log(googleUrl);
如果像上面嘗試要改數值,就會變成 error💁
要注意,const 宣告時一定要有值🧐
不過 const
宣告物件與陣列的資料時是可以改變其內容的,假設今天 const
一個物件,然後修改他,會發現內容的值變動了:
const family = {
mom: '老媽',
me: '小明',
sister: '小橙'
};
family.father = '爸爸';
family.mom = '小美';
使用上也能這樣:
const classMate = [];
classMate[0] = 'Jordan';const jordan = {};
jordan.girl = 'Zoe';
但物件本體不能改:
const jayFamily = {
mom: '杰哥媽',
me: '杰哥'
};jayFamily = 'fire';
console.log(jayFamily)//TypeError: Assignment to constant variable.
倘若不希望使其資料變動,可以加上一段語法
Object.freeze()
,就可以鎖住資料,不會被修改。
let 與 for 迴圈的淵源
為什麼用 let
比用 var
好?剛剛最前面已經提到不會污染到 window,再來舉一個常見的例子,監控列表是否被觸發事件:
var list = document.querySelectorAll('.list li');
var listLen = list.length;
for (var i = 0; i < listLen; i++) {
list[i].addEventListener('click', checkList, false);
}
function checkList() {
console.log(i+1);
}
因為 for迴圈 本身就會自己直接開始執行,而如果裡面的 function 需要事件觸碰的話,就會產生問題,但如果是 let
,他就會在 {}
中每次重新綁定,當然還是要注意 let 的特性,所以 checkList()
要在內部做宣告才行:
var list = document.querySelectorAll('.list li');
var listLen = list.length;
//將 for 迴圈的 var 改成 let
for (let i = 0; i < listLen; i++) {
function checkList() {
alert(i + 1);
}
list[i].addEventListener('click', checkList, false);
}
經過這些了解,我確實能理解到為什麼 ES6 建議都使用 let
和 const
了!!當然如果要使用 var
也可以拉,就是當這個變數經常會在各地出現,那使用 var
作為全域變數就OK😇
參考其他來源:
ES6 開始的新生活 let, const — iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天
Day 05: ES6篇 — let與const — iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天
ES6 Block Scope let const 塊級作用域 — JavaScript (JS) 教學 Tutorial