98

JavaScriptで関数式を実行するには、次の2つの方法があります。

名前付き関数式(NFE)

var boo = function boo () {
  alert(1);
};

匿名関数式

var boo = function () {
  alert(1);
};

そして、それらの両方をで呼び出すことができますboo();。匿名関数を使用する理由とタイミング、および名前付き関数式を使用するタイミングが本当にわかりません。それらの間にはどのような違いがありますか?

4

5 に答える 5

93

無名関数式の場合、関数は無名です — 文字どおり、名前がありません。割り当てている変数には名前がありますが、関数にはありません。(更新: ES5 まではそうでした。ES2015 [別名 ES6] の時点で、多くの場合、無名式で作成された関数は真の名前を取得します [ただし、自動識別子ではありません]、読み進めてください...)

名前は便利です。名前は、スタック トレース、コール スタック、ブレークポイントのリストなどで確認できます。名前は Good Thing™ です。

(古いバージョンの IE [IE8 以前] では、名前付きの関数式に注意する必要がありました。これは、完全に異なる 2 つの時点で 2 つの完全に別個の関数オブジェクトを誤って作成したためです [詳しくは、私のブログ記事Double take を参照してください]。 IE8 をサポートします [!!]。おそらく、無名関数式または関数宣言に固執するのが最善ですが、名前付き関数式は避けてください。)

名前付き関数式に関する重要な点の 1 つは、関数本体内の関数のその名前を持つスコープ内識別子を作成することです。

var x = function example() {
    console.log(typeof example); // "function"
};
x();
console.log(typeof example);     // "undefined"

ただし、ES2015 の時点では、多くの「無名」関数式が名前付きの関数を作成しています。これは、さまざまな最新の JavaScript エンジンがコンテキストから名前を推測することについて非常にスマートであることによって先行されていました。ES2015 では、無名関数式は という名前の関数になりますboo。ただし、ES2015+ セマンティクスを使用しても、自動識別子は作成されません。

var obj = {
    x: function() {
       console.log(typeof x);   // "undefined"
       console.log(obj.x.name); // "x"
    },
    y: function y() {
       console.log(typeof y);   // "function"
       console.log(obj.y.name); // "y"
    }
};
obj.x();
obj.y();

関数の名前の割り当ては、仕様のさまざまな操作で使用されるSetFunctionName抽象操作で行われます。

短いバージョンは基本的に、代入や初期化などの右側に無名関数式が現れるときです。

var boo = function() { /*...*/ };

(または、letまたはconstではなくvar)、または

var obj = {
    boo: function() { /*...*/ }
};

また

doSomething({
    boo: function() { /*...*/ }
});

(最後の 2 つは実際には同じものです)、結果の関数には名前 (boo例では ) が付けられます。

重要かつ意図的な例外があります: 既存のオブジェクトのプロパティへの割り当て:

obj.boo = function() { /*...*/ }; // <== Does not get a name

これは、新機能が追加される過程で発生した情報漏えいの懸念によるものでした。詳細については、別の質問への回答をご覧ください

于 2013-03-11T10:41:56.843 に答える
1

などの非推奨の機能に依存せずに問題の関数を参照できるようにする場合は、名前付き関数式を使用することをお勧めしますarguments.callee

于 2013-03-11T10:38:08.110 に答える