你知道JS全局變量是如何工做的嗎?

原文: 2ality.com/2019/07/glo…javascript

翻譯: 劉小夕html

在這篇博文中,咱們將研究 JavaScript 的全局變量是如何工做的。如:scripts的範圍,所謂的全局對象等等。java

更多文章可戳: github.com/YvetteLau/B…git

1.做用域

變量的詞法做用域(簡稱:做用域)是能夠訪問它的程序的區域。JavaScript 的做用域是靜態的(它們在運行時不會改變)而且它們能夠嵌套 - 例如:github

function func() { // (A)
    const foo = 1;
    if (true) { // (B)
        const bar = 2;
    }
}
複製代碼

if 語句引入的做用域(行B)嵌套在函數 func()(行A)的做用域內。瀏覽器

在示例中,funcif 的外層做用域。數據結構

2.詞法做用域

JavaScript 語言規範中,做用域是經過詞法做用域「實現」的。它們由兩部分組成:函數

  • 將變量名映射到變量值的環境記錄(能夠想象成是字典)。這是 JavaScript 存儲變量的地方。環境記錄中的一個 key-value 條目稱爲綁定。
  • 對外部環境的引用 - 表示當前環境所表明的做用域的外部做用域的環境。

所以,嵌套做用域樹能夠由嵌套環境樹表示。this

3.全局對象

全局對象是一個對象,其屬性是全局變量。spa

  • 無處不在:全局 this
  • 全局對象的其餘名稱取決於平臺和語言構造:
    • window:是引用全局對象的經典方式,但它只適用於普通瀏覽器環境; 不在 Node.jsWeb Workers 中。
    • self:在瀏覽器中隨處可用,包括 Web Workers。 可是 Node.js 不支持它。
    • global:僅在 Node.js 中可用。

全局對象包含全部內置全局變量。

4.全局環境

全局做用域是「最外層」做用域 - 它沒有外部做用域。它的環境是全局環境。每一個環境都經過由外部引用連接的一系列環境與全局環境相關聯。 全局環境的外部引用爲 null

全局環境結合了兩個環境記錄

  • 對象式環境記錄,其做用相似於普通環境記錄,但保持其綁定與對象同步。 在這種狀況下,對象是全局對象。
  • 聲明式環境記錄。

下圖顯示了這些數據結構。

接下來的兩個小節將解釋如何組合對象記錄和聲明式記錄。

4.1建立變量

爲了建立一個真正全局的變量,你必須處於全局做用域內 - 必需要在 scripts 的頂層:

  • 頂級 constletclass 在聲明式環境記錄中建立綁定。
  • 頂級 var 和函數聲明在對象式環境記錄中建立綁定。
<script>
    const one = 1;
    var two = 2;
</script>
<script>
    // All scripts share the same top-level scope:
    console.log(one); // 1
    console.log(two); // 2
    
    // Not all declarations create properties of the global object:
    console.log(window.one); // undefined
    console.log(window.two); // 2
</script>
複製代碼

此外,全局對象包含全部內置全局變量,並經過對象式記錄將它們給全局環境。

4.2讀取/設置變量

當咱們獲取或設置變量而且兩個環境記錄都具備該變量的綁定時,聲明式環境記錄將獲勝:

<script>
    let foo = 1; // 聲明式環境記錄
    globalThis.foo = 2; // 對象式環境記錄

    console.log(foo); // 1 (聲明式記錄獲勝)
    console.log(globalThis.foo); // 2
</script>
複製代碼

5.模塊環境

每一個模塊都有本身的環境,它存儲全部頂級聲明 - 包括導入。模塊環境的外部環境是全局環境。

結論:爲何JavaScript既有全局變量又有全局對象?

一般認爲全局對象是錯誤的。所以,較新的構造(如 constletclasses)會建立正常的全局變量,不會成爲全局對象的屬性。(在script做用域內時)。

值得慶幸的是,大多數用現代 JavaScript 編寫的代碼都存在於 ECMAScript 模塊和CommonJS 模塊中。每一個模塊都有本身的做用域,這就是爲何管理全局變量的規則不多對基於模塊的代碼很重要。

最後謝謝各位小夥伴願意花費寶貴的時間閱讀本文,若是本文給了您一點幫助或者是啓發,請不要吝嗇你的贊和Star,您的確定是我前進的最大動力。github.com/YvetteLau/B…

關注公衆號,加入技術交流羣

相關文章
相關標籤/搜索