主に言語とシステム開発に関して RSSフィード



2009-04-12

JavaScriptで,グローバル変数の存在判定をする3つの方法 ("window"の定義状況を確認したい)

|  JavaScriptで,グローバル変数の存在判定をする3つの方法 ("window"の定義状況を確認したい)のブックマークコメント



JavaScriptで,グローバル変数が存在するかどうか判定するための3つの方法。


3つのうち1つはよく使う。

残りの2つは,特殊な状況(WSHとの使い分けなど)で役立つ。



(1)「in window」 を使う

常套手段。

特定のオブジェクトが特定のプロパティを持っているかどうかを判定するためには,inを使う。


下記は,

  • 一つ目のボタンでグローバル変数をセットし
  • 二つ目のボタンでその存在判定を行なう

というコード。



<input type="button" value="グローバル変数をセット" onClick="f()">

<input type="button" value="グローバル変数の定義状況を判定" onClick="g()">

<script language="JavaScript">

function f()
{
	// グローバルで変数を定義する
	a = "hoge";
}


function g()
{

	if( "a" in window )
	{
		alert( "aは定義されています。" );
		alert( a );
	}
	else
	{
		alert( "aは未定義です。" );
	}
}

</script>

変数名は連想配列のキーである」というのを忘れずに,in文を使う時には a を""でくくる。

なお,inを使わずに


if( a == undefined )

とか


if( ! a )

としただけでは,「aは宣言されていません。」のエラーが出る。



また inを使うにしても,もっと高度なバージョンも存在する。

windowではなくapplyで「グローバルオブジェクトそのもの」を生成するのだ。


// グローバルを表すオブジェクトを生成
var global = ( function() { return this; } ).apply( null, [] );

if ( "a" in global )


参考:

JavaScript大域変数の存在確認

http://d.hatena.ne.jp/m-hiyama/20071126/1196037633


.apply(null) の本来の使い道:関数の可変長引数として配列を渡す

https://developer.mozilla.org/ja/A_re-introduction_to_JavaScript#.e9.96.a2.e6.95.b0



ところで,上記のコードは基本的には「"変数名" in window」という構文なわけだが,

"window" 自体の存在を判定したい場合はどうしたらよいのだろうか?


つまり,JavaScriptが

  • それとも,WSHのようなCUI環境で実行されているのか?

というのを判定したい場合,どうしたらよいか。


とりあえず以下の2つの方法がある。


(2)typeof演算子を使う

typeofは,パラメータの型を返す演算子。影は薄いがとても便利。


これを使うと(1)のコードは下記のようにも書ける。


<input type="button" value="グローバル変数をセット" onClick="f()">

<input type="button" value="グローバル変数の定義状況を判定" onClick="g()">

<script language="JavaScript">

function f()
{
	// グローバルで変数を定義する
	a = "hoge";
}


function g()
{

	if( typeof a != "undefined" )
	{
		alert( "aは定義されています。" );
		alert( a );
	}
	else
	{
		alert( "aは未定義です。" );
	}
}

</script>


typeofの参考:

JavaScriptで関数が存在するかどうかを確認する:typeofがfunctionかどうかで判定する

http://d.hatena.ne.jp/replication/20090121/1232465118

なお,「変数が存在して値がundefined」という場合にも「未定義」とみなされてしまうが,そこは許容する。


(3)try/catchする

3つ目の方法は,未定義エラーをキャッチするというもの。




<input type="button" value="グローバル変数をセット" onClick="f()">

<input type="button" value="グローバル変数の定義状況を判定" onClick="g()">

<script language="JavaScript">

function f()
{
	// グローバルで変数を定義する
	a = "hoge";
}


function g()
{

	try{
		a; // 未定義の場合,ここでわざとエラーを発生させる

		alert( "aは定義されています。" );
		alert( a );
	}
	catch( err ) // 未定義の場合
	{
		if( /*@cc_on ! @*/ false )
		{
			// IE用
			alert( err.number ); // エラー番号(-2146823279)
			alert( err.description ); // エラー内容
		}
		else
		{
			// FF用
			alert( err ); // エラー内容
		}
	}
}

</script>

これもクロスブラウザで動く。



活用

上の3パターンで使いやすいのは,(2)のtypeofだろう。


これを使って,「CUI/GUI両用のアラート関数」を書いてみる。



function myAlert( str )
{
	if( typeof( window ) == "undefined" )
	{
		// jsファイルをコマンドラインで実行時
		WScript.Echo( str );
	}
	else
	{
		// ブラウザで実行時
		alert( str );
	}
}

WScript.Echoとalertを書き分ける必要がなくなり,ライブラリをCUI/GUI両用にできる。


関連する記事:

JavaScriptでの例外設計 (throw,try-catch-finally構文のイメージと利用パターン) - 主に言語とシステム開発に関して

http://d.hatena.ne.jp/language_and_engineering/20101029/p1


IEを自動操作する時,IEのバージョンを判定したい (WSH JScriptで,IE7とIE8の違いを自動認識する) - 主に言語とシステム開発に関して

http://d.hatena.ne.jp/language_and_engineering/20101207/p1


JavaScriptで,動的に追加されたイベントリスナの実行順序を保証する方法 - 主に言語とシステム開発に関して

http://d.hatena.ne.jp/language_and_engineering/20081011/1223680301

 

リンク元