圖解javascript作用域
作用域訪問規則
let count = 0;
function func() {
console.log(count);
}
func();
下面我們來看看變數count
是如何被列印出來:
1. `func`函式呼叫,`console.log`列印`count`變數,查詢當前函式作用域,是否存在變數`count`;
2. 不存在繼續向上查詢,查詢模組作用域,發現`count`變數存在,並且列印出變數的值。
如果模組作用域依然不存在count
變數?
會繼續向上查詢,查詢全域性作用域是否存在count
變數,如果依然不存在,提示undefined
。
如下圖所示:
透過上面的示例程式碼,我們可以知道一個規則,作用域訪問順序:函式作用域 ——> 模組作用域 ——> 全域性作用域
提示:作用域訪問的方向是不可逆,只有由裡向外訪問,先函式,再模組,最後全域性;
作用域建立規則
JavaScript中的作用域是詞法作用域(相對於動態作用域)。
什麼叫詞法作用域?顧名思義,詞法作用域就是定義在詞法階段的作用域。換句話說,詞法作用域是由你在寫程式碼時將變數和塊作用域寫在哪來決定的。
無論函式在哪裡被呼叫,也無論它如何被呼叫,它的詞法作用域都只由函式被宣告時所處的位置決定,這就是JavaScript的詞法作用域。(除非你使用 with 或者 eval 欺騙它)
我們來看下面的例子:
let count = 0;
function func(name) {
console.log(count, name);
}
func('func');
程式碼執行,作用域建立順序:
1. 優先建立全域性作用域,如全域性window物件,或者掛載在全域性的函式或屬性;
2. 之後模組作用域被建立,`count`變數會掛載在模組作用域,`func`函式也是掛載在模組作用域;
3. 最後才是函式作用域,此時全域性作用域和模組作用域已建立生成,如果它需要使用外部的存在的變數或方法,只需向上查詢即可;
如下圖所示:
上圖中作用域建立是至上而下,我省略了表示遞進關係的線條。我們來歸納一下,作用域建立順序是:全域性作用域 ——> 模組作用域 ——> 函式作用域
在呼叫完成之後,作用域也會相應釋放。如果是存在閉包,作用域鏈就會被儲存,可以看看:閉包裝逼失敗(閉包使用) - 掘金。
總結
- 作用域訪問順序:函式作用域 ——> 模組作用域 ——> 全域性作用域
- 作用域訪問的方向是不可逆,只有由裡向外訪問
- 作用域建立順序是:全域性作用域 ——> 模組作用域 ——> 函式作用域
以上內容希望可以幫助到你,你的點贊、收藏是我更新的動力!!
參考
MDN文件
《你不知道的Javascript上卷》