2021年11月28日

グローバルオブジェクト

グローバルオブジェクトはどこでも利用可能な変数と関数を提供します。デフォルトで言語や環境に組み込まれています。

ブラウザでは window、Node.js では global、他の環境では別の名前になっているかもしれません。

最近では、すべての環境でサポートされるべきグローバルオブジェクトの標準的な名前として globalThis が言語に追加されました。すべての主要なブラウザでサポートされています。

ここでは、環境がブラウザと仮定して window を使用します。もし他の環境で実行させる可能性がある場合には、代わりに globalThis を使用するのが良いでしょう。

グローバルオブジェクトのすべてのプロパティへは直接アクセスできます:

alert("Hello");
// 同じ
window.alert("Hello");

ブラウザでは、varlet/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 (グローバルオブジェクトのプロパティにはなりません)

その値が重要で、グローバルで見えるようにしたい場合にはプロパティとして直接記述します:

// すべてのスクリプトがアクセスできるよう、現在のユーザ情報をグローバルに作成
window.currentUser = {
  name: "John"
};

// コードのどこかで
alert(currentUser.name);  // John

// あるいは、ローカル変数に currentUser がある場合には、
// 明示的に window から取得することも可能です
alert(window.currentUser.name); // John

とはいえ、グローバル変数は一般的には推奨されません。できるだけ少なくするべきです。関数が “入力” 変数を得て、明確な “結果” を出力するというコードデザインは、外部やグローバル変数を使用する場合よりも明確でエラーも少なく、テストもしやすいです。

polyfill のための使用

グローバルオブジェクトを使って、最近の言語機能のサポートをテストします。

例えば、組み込みの Promise オブジェクトが存在するかテストします(本当に古いブラウザでは存在しません):

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

存在しない場合、“polyfill” を作成できます(その環境でサポートされていないが、最近の標準としては存在する機能を追加)。

if (!window.Promise) {
  window.Promise = ... // 新しい言語機能のカスタム実装
}

サマリ

  • グローバルオブジェクトはどこでも参照可能な変数を保持しています。

    Array などJavaScript組み込みのものや、window.innerHeight(ブラウザのウィンドウの高さ)のような環境固有のものも含みます。

  • グローバルオブジェクトは普遍な名前 globalThis を持っています。

    …ですが、多くの場合、window(ブラウザ)やglobal(Node.js)のような、昔ながらの環境固有の名前で呼ばれます。

  • グローバルオブジェクトに値を保存するのは、プロジェクトで本当にグローバルであるものだけにすべきです。そして、その数はできるだけ少なくすべきです。

  • ブラウザでは、モジュールを使用していない限り、var で宣言されたグローバル関数や変数はグローバルオブジェクトのプロパティになります。

  • コードを将来性があり理解しやすくするために、グローバルオブジェクトのプロパティへは window.x のような直接アクセスしたほうがよいです。

チュートリアルマップ