JavaScriptでスコープの一番外側であるグローバルオブジェクトの取得方法について。ブラウザではwindowオブジェクトのことだが、サーバーサイドでは名前が異なるので環境に依存しないやり方をまとめる。
globalスコープ上でthis
var global = this;
しかしこれ、node.jsでは使えない。node.jsではスクリプトごとにスコープが切り離されており、thisはglobalでなく専用のmoduleオブジェクトを指しているため。
無名関数で取得する
var global = (function(){return this})();
無名関数にするとスコープに依存しなくなる(どんな関数やメソッド内に記載しても動く)のでよりベター。
しかし、strict modeでは動かない。strict modeでは関数内の暗黙のthisがglobalでなくundefinedにされてしまう。
"use strict";
var global = (function(){return this})();
console.log(global); //undefined
indirect eval call
ECMAScript 5ではindirect eval callなんていう技が存在する。evalに別名をつけて呼ぶとglobalスコープで実行されることを利用する。スコープ非依存でstrict modeの影響も受けない。
var e = eval, global = e("this");
//↓余計な変数を増やさない書き方
var global = ("global",eval)("this");
evalを間接的に呼べばいいので色々な書き方が存在するが、慣例としてカンマ演算子を使い、"global"などのダミー文字列をくっつける書き方がある。
完璧だがECMAScript5に準拠している環境でないと実行できない。例えばIE6などで動作しない。
Functionコンストラクタ
strict modeはFunctionコンストラクタまで伝搬しない。
var global = new Function("return this")();
//newは省略可
var global = Function("return this")();
Functionコンストラクタは現在使われている主要なすべての環境で使えるし、スコープ非依存でstrict modeの影響も受けない。というわけで、個人的にFunction("return this")()
をよく使っている。