iT邦幫忙

0

[快速入門前端 55] JavaScript:Global Scope 全域和 Local Scope 區域

  • 分享至 

  • xImage
  •  

Scope 作用域

Scope 是指在 JavaScript 程式中,一個變數可用 (或有效) 的範圍,而在這個有效範圍之外,變數是無法被使用的。舉個常見的例子,我們在 Function 中定義的變數,無法在函式外取得,這也是為什麼我們需要使用 return 回傳的方式將計算出來的結果返回到函式呼叫處的原因。
在 JavaScript 中,Scope 主要又分為兩大類 - Global Scope (全域) 及 Local Scope (區域)。

Global Scope 全域

在 Global Scope (全域) 中「宣告」的變數,也就是指在 JavaScript 檔案最外層 (所有 Function 和區塊之外) 被宣告的變數,被稱為全域變數 (Global Variables)。全域變數可以從網頁的任何地方,包括每個 Function、區塊中進行賦值、取值等操作。

如下範例,程式最外層中分別有兩種方法定義的全域變數 a 和 b,不管在單純的 if 區塊 或 function 函式 內都可以取得該變數。

let a = 1;
var b = 2;
if (true) {
    console.log(a); // 1
    console.log(b); // 2
}

function add() {
    console.log(a); // 1
    console.log(b); // 2
};

add(); // 呼叫 add()

Local Scope 區域

Local Scope (區域) 則和全域變數相反,是指在 Fucntion 函式 或 Block 區塊 內所宣告的變數,這類變數無法在宣告區域之外使用,所以被稱為區域變數。
而區域變數又因最早的 var 及後來在 ES6 新增的 let 兩種宣告方式有效範圍的差別分為 Function Scope 函式作用域 和 Block Scope 區塊作用域。

Function Scope 函式作用域

函式作用域是指在在函式中宣告的變數只能在函式區塊內作用,是基於 var 以函式作為區塊分隔的特性而來。也就是說在使用 var 時,所有不在 Function 內宣告的變數都是全域的。
有點複雜/images/emoticon/emoticon02.gif,以下用幾個範例來說明:

  1. var 是以 Function Scope 作為變數的有效範圍,在函式內宣告的變數只能在函式內作用
    function add() {
        var x = 2;
        console.log(x); // 2
    };
    add();
    console.log(x); // 報錯,無法取得 x
    
  2. 所有在函式外(包括 if 區塊內)宣告的變數對 var 來說都是全域的
    var a = 1;
    if (true) { // if 不是 function
        var b = 2; // 對 var 來說 b 也是全域變數,在任何地方都能使用
    }
    console.log(a); // 1
    console.log(b); // 2
    
  3. 判斷是區域或全域變數的基準是變數「宣告」的位置,而非首次賦值的位置
    var a; // 在最外層宣告
    function add () {
        a = 2 // 在函式中賦值
    }
    add();
    console.log(a); // 2
    
  4. 只要沒有在 Function 內進行宣告的都是全域變數 (包含沒有宣告直接在函式內使用的變數)
    // a 未宣告
    function add() {
        a = 3; // 只在 function 中賦值,沒有進行宣告,不算區域變數
        // 未宣告直接使用,不符合規範但 var 不會報錯
    };
    add();
    

Block Scope 區塊作用域

Block Scope 區塊 出現是基於 ES6 中新宣告方式 let 之作用域與 var 不同而來的概念,使用 let 宣告時,在區塊 ({})中宣告的變數只會在 {} 中有效,也就是說若在 if{} 條件區塊內使用 let 聲明變數,則該變數為區域變數。

  • 只要有被 {} 包裹,不管是條件區塊或任何區塊,let 宣告的變數都是區域變數
    if (true) {
        let a;
    }
    console.log(a); // not defined
    
    // 單純用區塊符號包裹也是區域變數
    {
        let b;
    }
    console.log(b); // not defined
    

全域區域變數名稱相同

當全域變數和區域名稱相同時,例如已有一全域變數 a 後又在函式內宣告區域變數 a,我們要怎麼知道現在在操作哪個變數呢?
答案是「找最近的」!
讓我們先來看看 var 的情境:

  • 在全域作用域宣告變數時,無論在哪都可以操作變數
    var x = 1; // 全域
    console.log(x); // 1
    function add() {
        console.log(x); // 1
    };
    add();
    console.log(x); // 1
    
  • 有一全域變數 x 又在函式內宣告一次 x,則會將兩個 x 視為不同的變數,找離自己最近的 (Function 內歸 Function 內,全域歸全域)
    var x = 1; // 全域
    console.log(x);
    function add() {
        var x = 5; // Function 內宣告同名變數,是區域變數
        console.log(x); // 5
        x = 10; // 會找最近的,所以在 Function 內操作的都是區域變數
        console.log(x); // 10
    };
    add();
    console.log(x); // 1 區域變數不影響全域變數
    
  • 函式內先使用變數再進行宣告,宣告前值為 undefined,不會拿全域變數的值
    var x = 1; // 全域
    console.log(x);
    function add() {
        console.log(x); // undefined
        var x = 5;
        console.log(x); // 5
    };
    add();
    console.log(x);
    

接著來看看 let:

  • 基本上 let 的規則與 var 大致相同,若在全域和區域有相同名稱的變數時,會找最近的
    let x = 1; // 全域
    console.log(x); // 1
    function add() {
        let x = 5;
        console.log(x); // 5
    };
    add();
    console.log(x); // 1
    
  • 不同的是 let 無法先使用再宣告,所以下範例會報錯
    let x = 1; // 全域
    console.log(x); // 1
    function add() {
        console.log(x); // 報錯,區域內宣告同名變數,所以與全域的 x 為不同變數
        let x = 5;
        console.log(x);
    };
    add();
    console.log(x);
    

結論

對於 let 和 var 這兩種宣告方式,其實在全域和區域的概念大致相同,差別在於兩者的「作用域」分別是 區塊 及 函式,只要分清楚兩種方法的差異就可以很容易弄懂其中的邏輯啦!


上一篇:[快速入門前端 54] JavaScript:Function 函式 (2) 參數和回傳
下一篇:[快速入門前端 56] JavaScript:Array 陣列 (3) 常見陣列操作方法
系列文章列表:[快速入門前端] 系列文章索引列表


圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言