iT邦幫忙

2021 iThome 鐵人賽

DAY 5
2

大家好!

今天我們就要正式介紹變數的宣告方式了!
我們進入今天的主題吧!


宣告沿革

JavaScript 目前有 3 種宣告方式,就是昨天提到的 varconstlet
其中的 constlet 就是為了解決舊版 JavaScript 問題而誕生的宣告方式。

事實上,ES6 問世前,宣告變數一直是 var 的工作,當時也不能宣告常數,因此造成許多編寫上的不便:

  1. 變數容易被汙染
  2. 全域變數會被定義為 window 的屬性
  3. 了解更多

宣告差異

接下來將會示範宣告方式的差異:

var

var 是基於函式來區分作用域。

var a = 0;
{
    var a = 1;
    console.log(a); // 1
}
console.log(a); // 1

a = 0a = 1 位於相同作用域,因此 a = 1 會覆蓋 a = 0 的宣告。

var b = 0;
(function () {
    var b = 1;
    console.log(b); // 1
})();
console.log(b); // 0

b = 0b = 1 位於不同作用域,因為 b = 1 位於函式內。

constlet

constlet 是基於區塊表示式(大括號)來區分作用域。

let c = 0;
{
    let c = 1;
    console.log(c); // 1
}
console.log(a); // 0

c = 0c = 1 位於不同作用域,因為 c = 1 位於區塊內。


宣告應用

接下來會將宣告方式應用於迴圈:

var

for (var i = 0; i < 2; i++) {
    setTimeout(function () {
        console.log(i);
    }, 1000);
}

// 2
// 2

怎麼會這樣?不應該是出現 01 嗎?
其實結果沒有錯,因為上方的迴圈有點像是下方的情況:

{
    {
        var i = 0;
        setTimeout(function () {
            console.log(i);
        }, 1000);
    }
    {
        var i = 1;
        setTimeout(function () {
            console.log(i);
        }, 1000);
    }
    {
        var i = 2;
        /* i < 2 === false */
    }
}

當計時器內的函式執行前,i 已經更新到 2了,又因為 var 宣告的變數只會於函式區分作用域,因此所有區塊的 i 將會一起更新,當然函式呼叫的 i 也只能是 2 了。

let

for (var i = 0; i < 2; i++) {
    setTimeout(function () {
        console.log(i);
    }, 1000);
}

// 0
// 1

這樣就能出現我們期待的結果了!
上方的迴圈有點像是下方的情況:

{
    {
        let i = 0;
        setTimeout(function () {
            console.log(i);
        }, 1000);
    }
    {
        let i = 1;
        setTimeout(function () {
            console.log(i);
        }, 1000);
    }
    {
        let i = 2;
        /* i < 2 === false */
    }
}

儘管計時器的函式是在 i 更新到 2 後才執行,但是因為 let 宣告的變數會於區塊表示式區分作用域,因此每個區塊的 i 都不會互相影響,也無法呼叫其他區塊的 i,當然函式呼叫的 i 就是相同區塊中的 i 了。


如果迴圈有計數器,請記得不能使用 const

差不多也到尾聲了。
如果對文章有任何疑問,歡迎於下方提問和建議!
我是 Felix,我們明天再見!


上一篇
JS 04 - 變數類型
下一篇
JS 06 - 建構函式
系列文
JavaScript 從 50% 開始,打造函式庫不是問題!46
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言