2022 年 7 月 1 日

全域物件

全域物件提供隨時可用的變數和函式。預設情況下,這些物件是內建於語言或環境中。

在瀏覽器中,它被命名為 window,在 Node.js 中,它被命名為 global,在其他環境中,它可能有不同的名稱。

最近,globalThis 已新增至語言中,作為全域物件的標準化名稱,應支援所有環境。它在所有主流瀏覽器中都受支援。

我們將在此處使用 window,假設我們的環境是瀏覽器。如果你的指令碼可能在其他環境中執行,最好改用 globalThis

所有全域物件的屬性都可以直接存取

alert("Hello");
// is the same as
window.alert("Hello");

在瀏覽器中,使用 var(不是 let/const!)宣告的全域函式和變數會變成全域物件的屬性

var gVar = 5;

alert(window.gVar); // 5 (became a property of the global object)

函式宣告也有相同的效果(主程式碼流程中使用 function 關鍵字的陳述式,不是函式表達式)。

請不要依賴這個!這種行為是為了相容性而存在的。現代腳本使用 JavaScript 模組,在模組中不會發生這種事。

如果我們改用 let,這種事就不會發生

let gLet = 5;

alert(window.gLet); // undefined (doesn't become a property of the global object)

如果某個值非常重要,你希望讓它在全域中可用,請直接將它寫成屬性

// make current user information global, to let all scripts access it
window.currentUser = {
  name: "John"
};

// somewhere else in code
alert(currentUser.name);  // John

// or, if we have a local variable with the name "currentUser"
// get it from window explicitly (safe!)
alert(window.currentUser.name); // John

話雖如此,一般不建議使用全域變數。全域變數應該盡量少。函式取得「輸入」變數並產生特定「結果」的程式碼設計比較清楚,比較不容易出錯,也比使用外部或全域變數更容易測試。

用於多重填充

我們使用全域物件來測試對現代語言功能的支援。

例如,測試內建 Promise 物件是否存在(在非常舊的瀏覽器中不存在)

if (!window.Promise) {
  alert("Your browser is really old!");
}

如果沒有(例如,我們在舊瀏覽器中),我們可以建立「多重填充」:加入環境不支援,但存在於現代標準中的函式。

if (!window.Promise) {
  window.Promise = ... // custom implementation of the modern language feature
}

摘要

  • 全域物件包含應該在所有地方都可用的變數。

    這包括 JavaScript 內建函式,例如 Array 和環境特定的值,例如 window.innerHeight,也就是瀏覽器中的視窗高度。

  • 全域物件有一個通用名稱 globalThis

    …但更常使用「舊式」環境特定的名稱來指稱它,例如 window(瀏覽器)和 global(Node.js)。

  • 我們應該只在它們對我們的專案真的是全域時,才將值儲存在全域物件中。而且要將它們的數量減到最低。

  • 在瀏覽器中,除非我們使用 模組,否則使用 var 宣告的全域函式和變數會變成全域物件的屬性。

  • 為了讓我們的程式碼更具備未來性,也更容易理解,我們應該直接存取全域物件的屬性,例如 window.x

教學地圖

留言

留言前請先閱讀…
  • 如果你有建議要如何改進,請 提交 GitHub 議題 或發起拉取請求,而不是留言。
  • 如果你看不懂文章中的某個部分,請詳細說明。
  • 若要插入少數幾個字的程式碼,請使用 <code> 標籤,對於多行程式碼 – 將它們包覆在 <pre> 標籤中,對於超過 10 行程式碼 – 使用 sandbox (plnkrjsbincodepen…)