スポンサーリンク

JavaScriptの動かないコード (中級編) evalでfunctionを作る時のエラー


以下のJavaScriptコードが意図した動作をしないのは,なぜですか。(制限時間1分)


やりたい事:
 文字列で関数を定義し,eval() で実行する。

<input type="button" value="「1」と表示" onClick="f()">

<script language="JavaScript">

function f()
{
	// 文字列を使って関数を定義
	var str = "( function() { alert( 1 ); } )";
	
	//alert( eval( str ) );
	
	// 関数を実行
	( eval( str ) )();
}

</script>



答え


firefoxでは正常に「1」と表示される。

しかしIEでは,( eval( str ) ) ( ) の所に来ると,「オブジェクトが指定されていない」というエラーになる。


なぜこうなるのか調べるために alert( eval( str ) ) してみると,

ffでは

function () {
    alert(1);
}

が表示され,期待通りの結果となる。


しかし,IEでは

undefined

となる。

undefinedであるような物に ( ) を付けて無理やり実行しようとしても,「何もオブジェクトが指定されていない」という返事が返ってくるのみである。


IEでは, eval( ) の中に無名関数を単独で書くと,関数として評価してもらえないらしい。



この路線でIEでも正しく動作するコードは2通りある。


まずは,実行したいという意思表示の「( )」を,eval の外側ではなく,内側に持ってくる方法。

<input type="button" value="「1」と表示" onClick="f()">

<script language="JavaScript">

function f()
{
	// 文字列を使って関数を定義
	var str = "(function() { alert(1); })";
	
	// 関数を実行
	eval( str + "()" );
}

</script>


あるいは,eval の内側で,関数オブジェクトをいったん何かの変数に保管してから実行する方法。

<input type="button" value="「1」と表示" onClick="f()">

<script language="JavaScript">

function f()
{
	// 文字列を使って関数を定義
	var str = "(function() { alert(1); })";
	
	// 関数を保管
	eval( "var g = " + str );

	// 関数を実行
	g();
}

</script>

これなら,どちらのコードもIE上で動作する。



ちなみに,冒頭のコードの文字列 str の中身は,かっこでくくる必要がある。くくらないと,firefoxでもエラーになり,関数を実行する事はできない。

無名関数をその場ですぐ実行したい場合には,

function(){ alert( 1 ) }();

ではなく,常に

( function(){ alert( 1 ) } )();

のように, ( ) でくくるのである。