JavaScript 中的作用域有幾種類型,主要包括:
MDN的說明:
The scope is the current context of execution in which values and expressions are "visible" or can be referenced. If a variable or expression is not in the current scope, it will not be available for use.
作用域就像是一個範圍概念,其中值或表達式是可見的或可被引用,如不在這個範圍內,將無法使用值或表達式。
JavaScript執行時,會創建一個全域的執行環境,在這裡宣告的變數叫做全域變數。全域變數在程式中任何地方都能使用到。
在Node.js中,全域物件是global
。
在瀏覽器中,全域物件是window
。
範例:
let global = "我是全域";
function sayHello() {
console.log(global); //在函式中印出變數global
}
sayHello(); // "我是全域"
console.log(global); // "我是全域"
因為global此變數在全域宣告,在任何地方都能被存取。即便有函式作用域,因「作用域鍊」的關係,會往外層找到此變數而印出。
變數只在函式內部存取。當函式被呼叫時,會產生函式的執行環境,當函式結束時,函式的執行環境也結束了,因此裡面宣告的變數就無法再被存取。
範例:
function sayHello() {
let innerVar = "我是函式內的變數";
console.log(innerVar); //?
}
sayHello();
console.log(innerVar); //?
執行結果:
呼叫sayHello函式,裡面有順利印出innerVar
變數的內容"我是函式內的變數"
。
但在全域呼叫innerVar
變數時,瀏覽器會報錯Uncaught ReferenceError: innerVar is not defined
證明此變數只作用在函式內,函式結束裡面變數也就無法存取。
適用let
和const
關鍵字宣告的變數,只能作用在區塊{}
內部,任何包含大括號 {}
的語法,例如if...else
、for
、while
、try...catch
等,都會形成區塊作用域。
if (true) {
let innerVar = "我是區塊變數";
console.log(innerVar); // "我是區塊變數"
}
console.log(innerVar); // 報錯
執行結果:innerVar
變數在if區塊裡面有順利印出innerVar
變數的內容。
而在區塊外面要存取時,瀏覽器一樣會報錯Uncaught ReferenceError: innerVar is not defined
。
如果是var關鍵字宣告的變數,在區塊外仍能存取!var只會被限制在function,其他都關不住它XD
不過現在很少使用var了,都使用let和const~
把剛剛題目改成var宣告:
if (true) {
var innerVar = "我是區塊變數";
console.log(innerVar); // "我是區塊變數"
}
console.log(innerVar); // 報錯
JavaScript會嘗試在當前的作用域尋找該變數,如找不到就往外層找,直到找到該變數或是到全域,全域仍找不到則會拋出ReferenceError錯誤。
let global = "我是全域變數";
function outerFunction() {
let innerVar = "我是函式內變數";
function innerFunction() {
console.log(global); // 在全域找到變數
console.log(innerVar); // 在outerFunction內找到變數
}
innerFunction();
}
outerFunction();
//"我是全域變數"
//"我是函式內變數"
以上分享~謝謝!
MDN - scope
JS 原力覺醒 Day04 - Function Scope / Block Scope
JS 原力覺醒 Day05 - Scope Chain
Javascript 的作用域 (Scope) 與作用域鏈 (Scope Chain) 是什麼?