[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が適切か。