読書会のエントリで式と文の所で例を挙げながら少し書いたけど、もう少し書きたいと思ったので改めて。
前回のエントリ内では4種類のfunctionを使った例を書いていましたが、それに関してminkeさんからコメントをいただいたので、もう少し考えてみることにしました。
function式を直接呼び出す時は「(function a(){alert(2);})();」と書くと良いということです。
こっからは結果がわかりやすいようにalertをconsole.debugに置き換えて書きます。
また、テストはFireBufで行ってます。
今回いただいた
(function a(){console.debug(2);})();
>>2
というコードは、エントリ内に記載していた例
function a(){console.debug(2);}();
> syntax error
の変形です。
しかし、前者は(に続くため関数式となり、後者は文頭からなので関数宣言になるという違いがあります。
この関数式の名前を関数として呼び出すと
(function a(){console.debug(2);})();
a();
>>2
> a is not defined
となります。
もう少しいじってみる。
(a = function(){console.debug(2);})();
a();
>>2
>>2
こう記述すると問題ない。
a = (function a(){console.debug(2);});>>2 無名関数の名前部分は無視
a();
とりあえず名前付きの関数式の名前は外部から呼び出す場合には無効。
読書会でお世話になったUnder Translation of ECMA-262 3rd Editionを紐解いてみると、11.2.5に『関数式 (Function Expressions)』という項目があるのですが、Syntaxが書いてないので名前か居ていいのかどうかわからない。
と思ったら13 関数定義 (Function Definition)に書いてた。
FunctionExpression : function Identifier[opt] ( FormalParameterList[opt] ) { FunctionBody }
っという事なので省略可能な識別子って事みたいなので記述する事には問題ないらしい。
内部から呼び出してみるとどうか。
(※無限再帰にならないように少し分岐
( a = function b(x){ console.debug(x); x > 0 ? b(--x) : 0 ; })(3); a(2);>>3 >>2 >>1 >>0 >>2 >>1 >>0
どうやら中からなら問題なく呼び出せる模様。
Safariだと名前付きの無名関数はerrorになるという記述を見たんだけど、ためしにWindows Safariで確認してみた所動いた。
ついでにIEとOperaでも動作確認したけどちゃんと動いた。
名前つきの無名関数の名前は、関数内のみ利用可能なんですね。
古いSafariだと問題があったりするのかもだけど。。。
--------------
FunctionExpression の Identifier が FunctionBody 内でのみ有効である事に加えJS1.5から追加された FunctionStatement の話しも読める、nanto_vi先生のエントリを読んだ方が勉強になりますね。
Function Expression Statements: Days on the Moon
この辺のお話しは、ちょうど前回の読書会で話題になりましたね。
コメントする