1. ホーム
  2. javascript

[解決済み] なぜ名前付き関数式を使うのか?

2023-01-13 02:49:37

質問

JavaScriptの関数表現には、2種類の方法があります。

名前付き関数式(NFE) :

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

匿名関数式 :

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

そして、どちらも呼び出すことができるのは boo(); . なぜ、いつ無名関数を使い、いつ名前付き関数表現を使うのかがよくわかりません。両者の間にどんな違いがあるのでしょうか?

どのように解決するのですか?

無名関数式の場合、その関数は 匿名  - であり、文字通り、名前を持ちません。代入先の変数には名前がありますが、関数にはありません。 (更新: ES5まではそうでした。ES2015 [別名ES6]では、しばしば無名式で作成された関数は真の名前[ただし自動識別子ではない]を取得します、お読みください...)

名前は便利です。名前は、スタックトレース、コールスタック、ブレークポイントのリストなどで見ることができます。名前は良いものです(Names are a Good Thing™)。

(IE の古いバージョン [IE8 以下] では、名前付き関数式に注意する必要がありました。2 つの完全に異なる関数オブジェクトを 2 つの完全に異なる時間に誤って作成してしまうためです。 ダブルテイク ]. IE8 [!] をサポートする必要がある場合は、無名関数式や関数 宣言 を使うのがベストでしょう。ただし、名前付きの関数式は避けてください)。

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

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

ES2015 では、多くの "anonymous" 関数式が名前を持つ関数を作成しますが、これは、さまざまな最新の 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() { /*...*/ }
});

(最後の二つは本当に同じものです) の場合、結果として得られる関数は名前( boo という名前になります。)

重要な、そして意図的な、例外があります。既存のオブジェクトのプロパティに割り当てることです。

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

これは、新しい機能が追加される過程で情報漏洩の懸念が生じたためです。詳細は別の質問に対する私の回答で説明しています。 はこちら .