練炭ブログ

X680x0、Irvine、DMonkey、Proxomitron などの情報を扱ってます。

DMonkey: 名前付き関数式はグローバルスコープに対する関数宣言として動作する

コメントなし»

ECMAScript で名前付き関数式(Named Function Expression: NFE)を使うと、その関数の内部でのみ関数名を参照できます。

一方、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

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です