今天要來介紹 JavaScript 的作用域,
JavaScript 是採用語法作用域(靜態作用域)
首先我們先來看一個函式執行:
function callName() {
var ming = '小明';
console.log(ming);
}
callName();
此時顯示的結果為 小明
但如果將 console.log()
放到函式外面時,
function callName() {
var ming = '小明';
}
callName();
console.log(ming);
會顯示 ReferenceError: ming is not defined
,
表示 ming
沒有被定義,
為什麼會這樣呢?
這就跟 JavaScript 的作用域有關係了
之前有說過 JavaScript 是直譯式語言,是利用直譯器來生成代碼後運行,
而作用域在代碼解析時,就已經確定作用域了,這就是語法作用域,
也就是當我們在撰寫程式碼的時候,作用域就已經決定好了,
而動態作用域是在調用函式的時候,才決定作用域。
以圖形表示作用域決定位置:
將上圖簡單整理的話變成:
語法作用域(靜態作用域):
在語法解析時,就已經確定作用域,也就是當我們在程式碼寫好的時候,作用域就已經決定好了。
動態作用域:
在調用函式的時候,才決定作用域。
JavaScript 的作用域是一層一層包著的,每一個函式都是一個作用域,而最外層是全域
當 fn1
需要使用變數,但作用域內沒有該變數時,會向外查找
當外層有該變數時會直接使用,
當外層沒有該變數時,會顯示 ReferenceError: xxx is not defined
接下來我們看一個範例:
var value = 1;
function fn1() {
console.log(value);
}
function fn2() {
var value = 2;
fn1();
}
fn2();
該範例顯示結果為 1
圖解:
此時 fn1
內沒有 value
這個變數,所以會向外查找,
而 JavaScript 的作用域為語法作用域,
因此 fn1
的外層為全域,而不是 fn2
,所以 value
會指向全域中的值 1
但如果是動態作用域的話,那結果會顯示 2
PS:這只是舉例動態作用域會顯示的結果而已,JavaScript 中這程式碼不管執行幾次都只會顯示 1
因為 fn1
被 fn2
調用時,fn1
外層的作用域會變成 fn2
的作用域,因此 value
會指向 fn2
中的值 2
以上就是關於作用域的部分了,明天說明執行環境與執行堆疊的部分。