Javascript 的作用域 (Scope) 與作用域鏈 (Scope Chain) 是什麼?
2022年10月11日
💎 加入 E+ 成長計畫 與超過 500+ 位軟體工程師一同在社群中成長,並且獲得更多的軟體工程學習資源
什麼是作用域 (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
判斷式中,就屬於塊級作用域。要注意的是,只有let
和const
定義的變數會屬於塊級作用域,如果是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();