Javascript 的作用域 (Scope) 與作用域鏈 (Scope Chain) 是什麼?

2022年10月11日

💎 加入 E+ 成長計畫 與超過 300+ 位軟體工程師一同在社群中成長,並且獲得更多的軟體工程學習資源

什麼是作用域 (Scope) ?

作用域這個概念,其實就像是範圍的概念。在 JavaScript 裡,「有作用」就是指可以被用上,可以被找到。所以,一個值(value)或者一個表達式(expression)可以被使用和找到的範圍,我們就稱之為作用域。

更正式一點來講,根據 MDN 的解釋,作用域指的是當前正在執行的上下文,也就是程式目前所處的情境。在這個情境內,我們可以輕鬆地存取各種值(value)或表達式(expression)。換句話說,如果有一個變數或表達式並不在這個情境中,那麼就不能輕易地使用它。

JavaScript 的作用域分為三種:

  • 全域 (Global Scope):當 JavaScript 程式碼被執行一開始時,就會創建一個全域執行環境,被定義在函式或塊級以外的變數,就會屬於全局作用域,這些變數也被稱之為全域變數 (Global variable),在程式碼中的任何地方都能被使用到。以下例子的 a 值就是在全局作用域的全域變數。

    var a = "全局作用域";
    
    function call() {
      console.log(a); // 全局作用域
      a = "哈囉全局作用域~~";
    }
    call();
    console.log(a); // 哈囉全局作用域~~
    
  • 函式作用域 (Function Scope):由函式所創建的作用域

    function scope() {
      let a = "函式作用域";
      console.log(a); // 函式作用域
    }
    // a 在此處不可用,因為 a 是函式作用域
    
  • 塊級作用域 (Block Scope):ES6 之後才出現,被定義在一個塊級中,如下面例子,在 if else 判斷式中,就屬於塊級作用域。要注意的是,只有 letconst 定義的變數會屬於塊級作用域,如果是 var 定義的變數會是只有函式作用域。

    function checkScope() {
      if (true) {
        let a = "塊級作用域";
        var b = "函式作用域";
      } else {
        // a 變數屬於 if 判斷式中的塊級作用域,在此處不可用
        // b 變數屬於 check 函式的作用域,在此處可用
        console.log(b); // 函式作用域
      }
      // a 在此處不可用,b 在此處可用
    }
    // a,b 在此處不可用
    

什麼是作用域鏈 (Scope Chain)?

當 JavaScript 使用每一個變數的時候,會先嘗試在當前作用域中尋找該變數,若在當前的作用域找不到該變數,會一直往父層作用域尋找,直到全局作用域還是沒找到,就會直接報錯,這一層一層的關係,就是作用域鏈。讓我們透過以下程式碼來了解:

let a = 100;
function find() {
  // 在 find 函式作用域中沒有變數 a,於是透過作用域鏈往父層尋找,
  // 在這邊的父層是全域,也就找到了 a 變數
  console.log(a); // 100
}
find();
🧵 如果你想收到最即時的內容更新,可以在 FacebookInstagram 上追蹤我們