自學日記

學習程式相關知識及學習法

0%

JS 宣告的var、const、let比較

Js 宣告的var、const、let比較

介紹宣告作用 及var、const、let比較

為何需要宣告

由於宣告變數會產生作用域,在多人開發的程式碼上比較好維護,假如未宣告,多人開發下變數名稱如果相同,會相互汙染(新成立的變數會蓋過之前成立的),因此強烈建議要宣告。

全域與區域汙染

比較下面兩個程式,我們可以知道,未宣告var的a,會影響到全域(function外),而宣告var後,函式會產生作用域,進而不會汙染到全域。

1
2
3
4
5
6
function fn() {
a = 0;
}
fn();
console.log(a);
// a=0
1
2
3
4
5
6
function fn() {
var a = 0;
}
fn();
console.log(a)
// a=is not defined

屬性與變數差異

屬性可以被刪除,變數則無法,這裡以學習影片中的範例說明:

1
2
3
4
5
6
7
8
9
10
11
12
13
a = 0;
console.log(a); // 輸出 0
console.log(window); // 全域物件 且裡面會有 a 屬性
delete window.a; // 用 delete 刪除屬性 a
console.log(a); // 輸出 a is not defined
console.log(window); // 全域物件的 a 也不見了


var b = 1;
console.log(window); // 全域物件 且裡面有 b
delete window.b; // 刪除屬性在這裡不起作用了 因為 b 是變數不是屬性了
console.log(window); // 所以這裡 b 還是存在
console.log(b); // 可以輸出 1

var

  1. var 是function作用域
  2. var會在window上
  3. 可被重複宣告

這裡補充關於var在for迴圈中影響,以兩段程式碼來說明:

由於var是函式作用域,而此處並無函式將其封裝,因此i會成為全域性變數,在每次迴圈run完後(由於在迴圈中i=5以不符合條件,而其又是全域變數),會”跳”出來顯現i值(此處範例為i=2)

1
2
3
4
5
6
7
8
for (var i = 0; i < 2; i++) {
setTimeout(() => {
console.log(i);
})
}

//2
//2

let被圈定在任何有中括號的範圍內。雖然上圖的for迴圈沒有將i圈定在中括號內,但ES6仍然在此機制上給let設定了屬於自己的作用域。不止如此,因為結果打印出了0和1,我們能肯定每一個i的值都有一個屬於自己的作用域,i並沒有被新的值所覆蓋。當setTimeout的回撥被啟動時,函式會去外層的作用域尋找i的值,而兩個回撥都擁有不同的作用域所以導致每次獲取i的值都是不同的

1
2
3
4
5
6
7
8
for (let i = 0; i < 2; i++) {
setTimeout(() => {
console.log(i);
})
}

//0
//1

參考資料:JS: 當 let 和 var 遇上for迴圈for迴圈繫結事件時,var和let宣告迴圈變數的區別

  • hoisting 提升
    可以參考文章 JS 中的變數提升 Hoisting

綜上三個var參考點,其實都是要相互理解的,比此多少都有點關係,也都很重要。

let

  1. let 是block(中括號)作用域
  2. let不會在window上
  3. 不可被重複宣告,但可以重新被賦值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    {
    let a=1
    let a=2//報錯
    }
    ``
    {
    let a=1
    a=2//可以
    }
  4. let無法在宣告之前取得值(暫時性死區)
    1
    2
    3
    4
    5
    6
    function fn(a) {
    console.log(a);//無法取得值
    let a = 2;
    console.log(a);// 2
    }
    fn(1);

    const

  5. const 不可重複被宣告,不可重新被賦值(const 宣告的是常數,常數是不能被重新賦值的)
  6. 同樣有暫時性死區
  7. 物件傳參考特性(能使用const盡量使用const)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    // 只需修改屬性值的話 就可以用 const 宣告的物件,請參考下方程式碼。
    const a = {
    name: "Amy",
    };
    a.name = "Ray";
    //允許

    // 修改整個物件的話 就不可以用 const 宣告,請參考下方程式碼。
    const a = {
    name: "Amy",
    };
    a = {
    name: "Ray",
    };
    //報錯