Scope 是指在 JavaScript 程式中,一個變數可用 (或有效) 的範圍,而在這個有效範圍之外,變數是無法被使用的。舉個常見的例子,我們在 Function 中定義的變數,無法在函式外取得,這也是為什麼我們需要使用 return
回傳的方式將計算出來的結果返回到函式呼叫處的原因。
在 JavaScript 中,Scope 主要又分為兩大類 - Global Scope (全域) 及 Local 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 (區域) 則和全域變數相反,是指在 Fucntion 函式
或 Block 區塊
內所宣告的變數,這類變數無法在宣告區域之外使用,所以被稱為區域變數。
而區域變數又因最早的 var
及後來在 ES6 新增的 let
兩種宣告方式有效範圍的差別分為 Function Scope 函式作用域
和 Block Scope 區塊作用域
。
函式作用域是指在在函式中宣告的變數只能在函式區塊內作用,是基於 var
以函式作為區塊分隔的特性而來。也就是說在使用 var
時,所有不在 Function
內宣告的變數都是全域的。
有點複雜,以下用幾個範例來說明:
function add() {
var x = 2;
console.log(x); // 2
};
add();
console.log(x); // 報錯,無法取得 x
var a = 1;
if (true) { // if 不是 function
var b = 2; // 對 var 來說 b 也是全域變數,在任何地方都能使用
}
console.log(a); // 1
console.log(b); // 2
var a; // 在最外層宣告
function add () {
a = 2 // 在函式中賦值
}
add();
console.log(a); // 2
// a 未宣告
function add() {
a = 3; // 只在 function 中賦值,沒有進行宣告,不算區域變數
// 未宣告直接使用,不符合規範但 var 不會報錯
};
add();
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
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) 常見陣列操作方法
系列文章列表:[快速入門前端] 系列文章索引列表