[JavaScript] グローバル変数の存在確認方法まとめ:typeofが無難

ポイント

if (typeof sample !== "undefined") alert("exists");

基本

JavaScriptにおいては、グローバル変数はグローバル・オブジェクト(ルートとなるオブジェクト)のプロパティという扱いになっている。

そのため、ウェブページならwindowがグローバル・オブジェクトなので、以下のように記述すればグローバル変数が存在するか確認できる。

if (window.hasOwnProperty("sample")) alert("exists");
if (window.sample) alert("exists");
if ("sample" in window) alert("exists");
if (typeof sample !== "undefined") alert("exists");

問題点

1. windowがグローバル・オブジェクトとは限らない

現在、JavaScriptという言語はウェブページだけでなく、ブラウザ向けアプリ(アドオン)、組み込み(Cocos2d-x)、ネイティブアプリ(Adobe AIR)、サーバ(Node.js)といったさまざまな環境で使われており、グローバル・オブジェクトが何かはその環境によって異なる場合がある。

そのため、クロスプラットフォームでグローバル・オブジェクトを確実に取得するためには、以下のように記述する必要がある。

var global = new Function("return this")();

しかし、グローバル・オブジェクトの存在確認のために以下のように記述するとなると、あまりにも冗長といえる。

if (new Function("return this")().sample) alert("exists");

2. 宣言されていない変数を式の中で使うとReferenceErrorが出てしまう

JavaScriptでは、オブジェクトの宣言されていないプロパティを使おうとしてもundefinedが返るだけだが、宣言されていない変数ではReferenceErrorが出てしまう。

if (window.sample) alert("exists"); 	// エラーなし
if (sample) alert("exists"); 			// ReferenceError
if (sample || false) alert("exists");	// Firefox以外ではReferenceError

グローバル変数もグローバル・スコープのローカル変数なので、同じ問題がある。

よって、以下のように記述するのはよくない。

if (sample) alert("exists");

try-catch構文でReferenceErrorをキャッチするという手段もあるが、余計に冗長。

3. typeofを使うのも問題

if (typeof sample !== "undefined") alert("exists");

(1) 「sample = undefined;」のときに問題

実際には変数が宣言され、値がundefinedのときにも存在しないということになってしまう。

(2) 素の文字列と比較するのでタイプミスが起きやすい

いわゆるマジックストリングの問題。

結論:typeofが無難か

上記のとおり、どれもなんらかの問題を抱えているが、可読性と記述量の少なさを考えればtypeofが適切か。