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、區塊中進行賦值、取值等操作。

如下範例,程式最外層中分別有兩種方法定義的全域變數 ab,不管在單純的 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);
    

結論

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


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


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言