在了解什麼是區塊範疇(block scope)以及函式範疇(function scope)之前,要先知道什麼是範疇(scope)。
當我們在程式中引進變數時,我們必須給予這些變數一個安置它們的空間,如此一來我們才能在需要的時候將它們從那個空間中找出來使用。
而範疇(scope)就如同那個安置變數的空間。
首先要學習的部分是函式範疇(function scope)。
函式範疇的定義是變數在 function(){...}
以外的地方為不可見,只有在函式中才可以使用那些被宣告的變數。
JavaScript在 ES6 之前是透過 var
宣告變數,所以會建立以函式為範疇的變數。
來看看這個測試例子:
function scope(){
var a = 1;
console.log(a);
let b = 2;
if(b > 1){
console.log(a);
}
}
scope();
console.log(a);
透過結果可以得知在 scope函式外的變數 a
無法得到內部變數 a
的值。
再看看另外一個測試例子:
function scope(){
let b = 2;
if(b > 1){
var a = 2;
let c = 3;
}
console.log(a);
console.log(c);
}
scope();
變數 a
是透過 var
宣告,因此變數屬於函式範疇,所以當寫在 if
條件句中,在外部也一樣可得到變數 a
的值 2
。
而變數 c
是透過 let
宣告,因此變數屬於區域範疇,所以當寫在 if
條件句中時,外部無法得到變數 c
的值 3
。
區域範疇的定義是變數在 {...}
以外的地方為不可見的,只有在 {...}
裡面才可以使用到那些被宣告的變數。
在ES6之後可以透過 let
與 const
兩種新的宣告方式,建立以區塊為範疇的變數。
來看看測試例子:
const foo = 3;
if(foo > 1) {
let bar = foo * 2;
console.log(bar);
}
console.log(bar);
變數 bar
只在 {...}
的區塊有效,所以只在 if
條件句中可被讀取,而外部則讀取不到。
JavaScript 環境建立時,會先將所有的變數、函數先存入記憶體空間(但這過程並不包含指定給變數的值及函式的執行內容,會在原地等待被執行)
因此,變數、函式會因為先行存入記憶體的緣故,而提升到程式碼的最上端。
而這個會將宣告的變數、函式從原本撰寫的位置提升到程式碼最上端的行為也稱為提升(hoisting)。
先看看關於變數提升(hoisting)的例子:
console.log(a);
var a = 3;
console.log(a);
因為提升(hoisting),所以當透過 console.log(a)
時,會發現變數 a
的值為 undefined
而非 a is not defined
。
這代表 變數
a 已經被宣告,但還沒有被使用。
而第二個 console.log(a)
因為已經將值指定(assign)給變數 a
,所以可以得到值為 3
。
再看看關於函式提升(hoisting)的例子:
console.log(test());
function test() {
return 2;
}
觀念同於變數,會先將函式名稱 test
存入記憶體空間中,所以即使是先執行 console.log(test());
也依然可以得到值 2
。
關於範疇(Scope)與提升(Hoisting)的學習就告一段落囉
明天見~