var、let、const 的差異
以下為我今年參加iT邦幫忙鐵人賽寫的文章,原文連結:
但是老師教我用 var 宣告變數,但我也看到有同學用 let 與 const 宣告變數,這是怎麼一回事呢?
//建立一個變數郭靖(guoJing)
var guoJing;
也可以看到這樣:
//建立一個建立一個名為黃蓉(huangRong)的變數,給她'打狗棒法'的值
let huangRongKungFu = '打狗棒法';
//建立一個洪七公(hongQigong)的常數,給他「北丐」的值
const hongQigong = '北丐';
var 、 let 、 const 這三兄弟到底有甚麼差別呢?
原來除了用var宣告變數之外,在ES6之後,變數區分為變數與常數,透過 var 與 let 宣告「變數」,透過const宣告「常數」。
var 和 let 最大的區別在於「作用域」不同,這一點我們先放在心上,之後再深入探討。
在這裡補上let與var作用域的區別:
- var 是以function為作用域。
- let 則是以大括號{}區塊的程式碼為作用的範圍。
作用域外層的程式捉不到作用域內的宣告的變數,但是作用域內的程式可以捉到外層的變數。
先來看看var:
//建立一個變數郭靖(guoJing)
var guoJingKungFu;
console.log(guoJingKungFu);
//未賦值,所以出現的結果為 undefined
guoJingKungFu = '降龍十八掌';
console.log('郭靖使出 ' + guoJingKungFu);
//結果為"郭靖使出 降龍十八掌"
guoJingKungFu = '空明拳';
console.log('郭靖使出 ' + guoJingKungFu);
//結果為"郭靖使出 空明拳"
var guoJingKungFu = '九陰真經';
//再次用var宣告 guoJing = '九陰真經';
console.log('郭靖使出 ' + guoJingKungFu);
//結果為"郭靖使出 九陰真經"
使用var的時候,同一個變數名稱可以再重新「宣告」,重新賦值。
再看看使用 let
的狀況:
//建立一個建立一個名為黃蓉(huangRong)的變數,給她'打狗棒法'的值
let huangRongKungFu;
huangRongKungFu = '打狗棒法';
console.log('黃蓉使出 ' + huangRongKungFu);
//結果為"黃蓉使出 打狗棒法"
huangRongKungFu = '落英神劍掌';
console.log('黃蓉使出 ' + huangRongKungFu);
//結果為"黃蓉使出 落英神劍掌"
let huangRongKungFu = '蘭花拂穴手';
//Uncaught SyntaxError: Identifier 'huangRong' has already been declared
使用 let 比使用 var 來宣告變數嚴謹,如果宣告時未賦值,並不會以undefined初始化,所以從宣告到初始化這段時間會無法使用,這個時間差稱為「暫時死區」。
let 能重複賦值,禁止於同個區塊作用域重複宣告,如果重複宣告會出現:
「Uncaught SyntaxError: Identifier ‘huangRong’ has already been declared」
提醒你已經用 let 宣告過這個變數了。
讓我們來試試 const:
//建立一個洪七公(hongQigong)的常數,給他「北丐」的值
const hongQigong = '北丐';
console.log('洪七公是 ' + hongQigong);
hongQigong = '美食家';
//Uncaught TypeError: Assignment to constant variable.
const hongQigong = '美食家';
//Uncaught SyntaxError: Identifier 'hongQigong' has already been declared
const 是用來宣告常數,也就是不會變動的常量,所以禁止於同個區塊作用域重複宣告,也不能重新賦值。而且宣告時一定要給值。
重複宣告會告訴你:
「Uncaught SyntaxError: Identifier ‘hongQigong’ has already been declared」
重複賦值則會提醒你:
「Uncaught TypeError: Assignment to constant(持續的) variable.」
因為以上這些區別,使用 var 、 let 、 const 來宣告變數的時機與場景有不同的區別,語意上也有明確區分。而沒有經過 var 、 let 與 const 宣告就直接賦值使用的變數會變成全域變數。
const 有一個例外,就是在宣告物件時,因為物件是 call by reference ,變數參考的是物件存放的位置,當修改物件屬性的時候,不會改變物件參考的記憶體位置,所以用 const 宣告物件時,其屬性是可以修改的,但是重新賦值則是禁止的。