ECMAScript で名前付き関数式(Named Function Expression: NFE)を使うと、その関数の内部でのみ関数名を参照できます。
- mixi Engineers' Blog » 詳細 ECMA-262-3 第5章 関数
- [JavaScript]名前つき関数オブジェクトのスコープ / LiosK-free Blog
- IE8- は名前付き関数式を関数宣言としても扱う - @think49の日記
一方、DMonkey における NFE はグローバルスコープに対する関数宣言として動作します(同じ関数どころか、どこからでも参照できてしまいます)。
function foo () {
var a = function bar () { alert ('baz'); };
}
foo ();
bar (); // baz
トップレベルで普通に関数や変数宣言をした場合と同じ扱いになるようです。Global オブジェクトに入るわけではないので、alert (Global.hasKey ('bar'));
は false です。
これはつまり関数内で NFE を使ってしまうと外部にまで晒されるということですが、逆に、あえて NFE を使うことで関数内からグローバル関数を定義することが出来る、とも言えます。
以下のように prototype への読み書きも出来るので、オブジェクトを定義することも出来ます。
(function () {
void function Foo () { };
Foo.prototype.bar = function () { alert ('baz'); };
}) ();
var x = new Foo ();
x.bar (); // baz
最初のサンプルコードでは代入式という形で関数式を記述しましたが、今度は頭に void、末尾に ; を着ける方法をとっています。他に、true && function Foo () { };
といったパターンでも動作するので、関数式であればなんでもOKっぽいです。
なお、関数内からグローバルスコープでオブジェクトを定義したい場合、普通に考えると以下のようなコードになると思いますが、DMoneky ではエラーで動作しません。
(function () {
Foo = function () { };
Foo.prototype.bar = function () { alert ('baz'); };
}) ();
var x = new Foo ();
x.bar (); // Exception: ENameError() => bar
(function () {
function x () { }
x.prototype.bar = function () { alert ('baz'); };
Foo2 = x;
}) ();
var x2 = new Foo2 ();
x2.bar (); // Exception: ENameError() => bar