JavaScript: 使用 var, let, const 宣告究竟差在哪呢?

JavaScript

在 JavaScript 中,經常使用var, let, const這三個數來宣告,究竟這三個有什麼不同呢?下面來詳細說明(^_^)

註:此篇文章有多個程式碼輔助解釋,篇幅較長,您也可以拉到最底部看比較表格。

由來

var, let, 以及 const 都是在 JavaScript 用來做變數宣告的保留字,在 JavaScript 早期只有 var,直到 ES2015 (ES6) 時才加入了 letconst

關於 var

重點

  • var函數作用域(function scope),若在函數外宣告則為全作用域(global scope)
  • 僅有 function scope 能夠關住 var(容易污染)
  • var 宣告的變數,可以重新被宣告 & 賦值
  • 變數提升,若先提取變數,再使用 var 宣告,會出現 undefined

接著會用四個範例題目,來幫助解釋這四個重點 ٩(ˊᗜˋ )و

var 為全作用域

var可以為全作用域(global scope)函數作用域(function scope)。這代表在函式外面定義的變數可以全域訪問,在特定函數內部定義的變數可以在函數內部存取。(補充:未宣告的變數也會放在全域變數)

  • 範例 1:全域宣告變數a,我們可以在程式的任何地方抓到a
1
2
3
4
5
6
var a = 100;
function fn() {
console.log(a);
}
fn();
console.log(a);
output: 10 10
  • 範例 2:僅有 function scope 能夠關住 var,變數“a”在函數內使用 var 宣告。如果使用者在函數之外存取,則會顯示ReferenceError: a is not defined
1
2
3
4
5
6
function fn() {
var a = 10;
console.log(a);
}
fn();
console.log(a); //var無法在function外被存取;
output: 10
ReferenceError: a is not defined
  • 範例 3:var 宣告的變數,可以重新被宣告&賦值
1
2
3
4
var a = 10;
var a = 8;
a = 7;
console.log(a);
output: 7
  • 範例 4:如果使用者在宣告之前使用 var 變數,因為變數提升(Hosting)的關係。在執行函數之前,會優先將 var 變數放入記憶體。要注意的是:這只是在記憶體有這變數的空間,但尚未初始化。這也是為何會拿到 undefined 的原因。
1
2
console.log(a);
var a = 10;
output: undefined

關於 let

重點

  • let區塊作用域(block scoped),無法在{block}之外存取它
  • 變數提升(Hosting),但因為 let 不會幫忙初始化,而是存在暫時執行死區(TDZ),因此let不能在宣告前使用,不能多次宣告。
  • 範例 1:正常運行的樣子
  • 1
    2
    3
    4
    5
    6
    7
    let a = 10;
    function f() {
    let b = 9;
    console.log(b);
    console.log(a);
    }
    f();
    output:9
    10
    • 範例 2: let宣告無法在{block}之外存取變數b,因此會出現ReferenceError: b is not defined
    1
    2
    3
    4
    5
    6
    function fn() {
    let b = 9;
    console.log(b);
    }
    fn();
    console.log(b);
    output:9
    ReferenceError: b is not defined
    • 範例 3: let宣告的變數不能重複宣告,但可以改變其值
    1
    2
    let a = 10;
    let a = 10;
    output:Identifier 'a' has already been declared
    • 範例 4: let宣告的變數不能重複宣告,但可以改變其值
    1
    2
    3
    let a = 1;
    a = 2;
    console.log(a);
    output:2
    • 範例 5:let作用域僅在{block}內,因此在{block}外可以使用同個變數名稱宣告
    1
    2
    3
    4
    5
    6
    let a = 10;
    if (true) {
    let a = 9;
    console.log(a);
    }
    console.log(a);
    output:9
    10
    • 範例 6: 在let宣告前先提取變數a,但因為let不會幫忙初始化,而是存在 TDZ,因此會出現Cannot access 'a' before initialization
    1
    2
    console.log(a);
    let a = 10;
    output: Cannot access 'a' before initialization

    關於 const

    常數(constant)又稱定數,是指一個數值固定不變的數,例如圓周率,與之相反的是變數。

    重點

    • const區塊作用域(block scoped),無法在{block}之外存取它
    • 使用const宣告的變數不能改變,亦不能重複宣告。
    • 若使用 const 宣告,不能改變其屬性,但能夠改變內含的東西。

    相對其他的宣告方式,const規定相對嚴格,所以不像var會有很多花裡胡哨的例外行為,是個很乖巧的好孩子呢(๑¯◡¯๑)。

    • 範例 1: 使用const宣告的a,不能夠重新賦值,會出現TypeError
    1
    2
    3
    4
    5
    6
    const a = 10;
    function fn() {
    a = 9;
    console.log(a);
    }
    fn();
    output: TypeError: Assignment to constant variable.
    • 範例 2: const同樣為區塊作用域(block scoped),在{block}外不能存取,會出現 ReferenceError: a is not defined
    1
    2
    3
    4
    function fn() {
    const a = 9;
    }
    console.log(a);
    output: ReferenceError: a is not defined
    • 範例 3:使用 const 宣告,不能改變物件,但能夠替換物件內的東西。
    1
    2
    3
    4
    5
    6
    7
    const a = {
    prop1: 10,
    prop2: 9,
    };
    a.prop1 = 3;

    console.log(a);
    output: { prop1: 3, prop2: 9 }
    • 範例 4:const宣告不能改變物件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    const a = {
    prop1: 10,
    prop2: 9,
    };

    a = {
    prop1: 20,
    };

    console.log(a);
    output: TypeError: Assignment to constant variable.

    範例 3 和 4 可以想像成,乖寶寶const宣告了 a 是一盒工具箱,你可以往裡面加把手、螺絲起子等等工具,也可以拿走裡面的工具,但你不能再說工具箱是醫藥箱,乖寶寶const宣告了醫藥箱就是醫藥箱!(除非被{…}包住了)

    我自己是這樣記憶的,會比較好懂 ٩(ˊᗜˋ )و


    看了上面這麼多範例,感覺就缺少一個東西,那就是比較表格!我特別整理了一個表格給大家參考 o(^▽^)o

    var, let, const 比較表格

    宣告準則(建議)

    為了防其他的程式碼被宣告所污染到處都拿得到 var 宣告的變數,就像任何人都可以把警察局說成是教堂,把板手說成是棒棒糖,想起來有點可怕 ╰(°▽°)╯,所以建議的宣告順序如下:

    1. const
    2. let
    3. var

    當然實際還是依照需求而定,希望今天的文章有幫助到您!

    另外在文章內提到的變數提升,也歡迎參考我另外一篇文章的解釋:JavaScript: 變數提升 hoisting 到底是什麼?

    文章內容是根據以下參考資料整理+自己繪圖而得,如果有任何建議都歡迎提供唷 (´・∀・`)

    參考資料:

    五倍學院 - 為你自己學 JavaScript 課程內容

    ExplainThis:在 JavaScript 中用 var, let, 以及 const 有什麼差別?什麼時候該用哪個?

    Difference between var, let and const keywords in JavaScript

    评论