圖解javascript作用域

HerryLo發表於2023-04-07

圖解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上卷》

冴羽 · JavaScript深入之執行上下文

相關文章