Scheme の lambda あるいは Objective Caml の fun と JavaScript の function が微妙に違うという話です。
[pukiwiki]
JavaScript の function 式は無名一級関数を作るための構文で、以下のように使います。
function (a1, a2, …) { body; }
これとは別にプログラムのトップレベルで利用可能な function 文もあって、名前のついた関数を宣言することができます。
function f(a1, a2, …) { body; }
ECMAScript の仕様書では前者は FunctionExpression、後者は FunctionDeclaration という構文要素として説明されています。でも、function という同じキーワードが使われているために僕は混乱しがちです。
Scheme の場合、FunctionExpression と FunctionDeclaration に相当するのは、それぞれ lambda と define です。Objective Caml の場合は、fun/function と let/let rec というように区別されています。この恩恵について考えることは、これまでなかったのですが、JavaScript で以下のような構文的に正しくないコードをしょっちゅう書いてしまうことから気づきました。
function () { body; }();
これは、局所環境を作るために無名関数を作りその中で body を実行しているつもりです。でも、ECMAScript としてはこれは FunctionDeclaration の出来損ない、つまり関数名を書き忘れたものと思ってしまいます。((あまり真面目に仕様書を読んでいないのだけれども、ECMAScript においても式は文だから、FunctionExpressionの適用をする文と見做せるのではないかとも思うのだけど、どこか勘違いしているのかな?ちなみに、僕が使っている JavaScript は Apple Safari のものです。Mozilla Rhino でも同様の振舞いを確認しています。))
で、どうみても上の式を FunctionExpression と認識せざるを得ないような書き方として二通りがあります。
var _ = function () { body; }();
あるいは
(function () { body; })();
ほかにもあるかな?みなさんはどれを使っていますか?
[/pukiwiki]
ECMAの仕様書をよく見てみると、名前付の FunctionExpressionは、実行された環境に名前を束縛するわけじゃないようですね(sec. 13: semantics参照)。あたらしくObjectをつくって、そのpropertyになるようです。FunctionDeclarationと意味的に違うので区別しないといけなくなっちゃったのでしょう。ややこしや。
文法的な曖昧さについては、Toplevelの statementに出てくる式の種類を制限して(FunctionDeclarationが出てこないようにして)回避しているような気がします。
ちなみに、世のjavascriptライブラリでは (function(){body})() が趨勢な気がします。
ECMAScriptの仕様のことを教えてくれてありがとうございます。しっかりと理解しようと思うときに、仕様書が自然言語まじりの疑似言語で書かれているとよくわからなくなりますね。(function () { body })() は、ぼくのお気に入りにもなりました。