wake-up-neo.com

Warum benannte Funktionsausdrücke verwenden?

Funktionsausdrücke können in JavaScript auf zwei verschiedene Arten ausgeführt werden:

Benannter Funktionsausdruck (NFE)

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

Anonymer Funktionsausdruck :

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

Und beide können mit boo(); aufgerufen werden. Ich kann wirklich nicht verstehen, warum/wann ich anonyme Funktionen und wann benannte Funktionsausdrücke verwenden sollte. Welchen Unterschied gibt es zwischen ihnen?

81

Im Fall des anonymen Funktionsausdrucks lautet die Funktion anonymous - buchstäblich hat sie keinen Namen. Die Variable, der Sie sie zuweisen, hat einen Namen, die Funktion jedoch nicht. (Update: Das war durch ES5 wahr. Ab ES2015 [aka ES6] erhält eine Funktion, die mit einem anonymen Ausdruck erstellt wurde, oft einen echten Namen, lesen Sie weiter ...)

Namen sind nützlich. Namen können in Stack-Traces, Anruf-Stacks, Listen von Haltepunkten usw. gesehen werden. Namen sind eine gute Sache ™.

Sie müssen sich vor benannten Funktionsausdrücken in älteren Versionen von IE (IE8 und darunter) hüten, da IE versehentlich zwei vollständig separate Funktionsobjekte zu zwei völlig unterschiedlichen Zeitpunkten erstellt (mehr in meinem Blogartikel Doppeltnehmen ). Wenn Sie IE8 unterstützen müssen, ist es wahrscheinlich am besten, bei anonymen Funktionsausdrücken oder bei der Funktion deklarationen zu bleiben, aber benannte Funktionsausdrücke zu vermeiden.

Ab ES2015 erstellen jedoch viele "anonyme" Funktionsausdrücke Funktionen mit Namen, und das war vor allem bei verschiedenen modernen JavaScript-Engines der Fall, die das Nachahmen von Namen aus dem Kontext recht schlau machen. In ES2015 führt Ihr anonymer Funktionsausdruck zu einer Funktion mit dem Namen boo. Dies ist überall in der Spezifikation verstreut, anstatt an einer Stelle mit einer Reihe von Regeln definiert zu werden: Suchen Sie nach Vorkommen von "SetFunctionName", das sich aktuell in befindet:

Die Kurzversion ist im Allgemeinen immer dann, wenn ein anonymer Funktionsausdruck auf der rechten Seite von etwa einer Zuweisung oder Initialisierung angezeigt wird:

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

(oder let oder const anstelle von var) oder

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

oder

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

(die letzten beiden sind wirklich dasselbe), die resultierende Funktion hat einen Namen (boo, in den Beispielen).

Es gibt eine wichtige und beabsichtigte Ausnahme: Zuweisung zu einer Eigenschaft eines vorhandenen Objekts:

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

Dies war auf Bedenken hinsichtlich des Informationslecks zurückzuführen, als das neue Feature durchlaufen wurde. Details in meiner Antwort auf eine andere Frage hier .

78
T.J. Crowder

Benennungsfunktionen sind nützlich, wenn sie sich selbst referenzieren müssen (z. B. für rekursive Aufrufe). Wenn Sie einen Literal-Funktionsausdruck direkt als Argument an eine andere Funktion übergeben, kann der Funktionsausdruck nicht direkt im ES5-Modus referenziert werden, wenn er nicht benannt wird.

Betrachten Sie zum Beispiel diesen Code:

setTimeout(function sayMoo() {
    alert('MOO');
    setTimeout(sayMoo, 1000);
}, 1000);

Es wäre unmöglich, diesen Code so sauber zu schreiben, wenn der an setTimeout übergebene Funktionsausdruck anonym wäre. Wir müssten es stattdessen vor dem setTimeout-Aufruf einer Variablen zuweisen. Mit einem benannten Funktionsausdruck ist dieser Weg etwas kürzer und übersichtlicher.

In der Vergangenheit war es möglich, Code mit Hilfe eines anonymen Funktionsausdrucks zu schreiben, indem arguments.callee ...

setTimeout(function () {
    alert('MOO');
    setTimeout(arguments.callee, 1000);
}, 1000);

... aber arguments.callee ist veraltet und im strikten ES5-Modus absolut verboten. Daher empfiehlt MDN:

Verwenden Sie arguments.callee() nicht, indem Sie entweder einen Funktionsausdruck angeben oder eine Funktionsdeklaration verwenden, bei der eine Funktion sich selbst aufrufen muss.

(Hervorhebung meines)

21
Mark Amery

Wenn eine Funktion als Funktionsausdruck angegeben ist, kann dieser einen Namen gegeben werden.

Es wird nur innerhalb der Funktion verfügbar sein (außer IE8-).

var f = function sayHi(name) {
  alert( sayHi ); // Inside the function you can see the function code
};

alert( sayHi ); // (Error: undefined variable 'sayHi')

Dieser Name ist für einen zuverlässigen rekursiven Funktionsaufruf gedacht, auch wenn er in eine andere Variable geschrieben wird.

Außerdem kann der NFE-Name (Named Function Expression) mit der Object.defineProperty(...)-Methode folgendermaßen überschrieben werden:

var test = function sayHi(name) {
  Object.defineProperty(test, 'name', { value: 'foo', configurable: true });
  alert( test.name ); // foo
};

test();

Hinweis: Mit der Funktionsdeklaration ist dies nicht möglich. Dieser "spezielle" interne Funktionsname wird nur in der Funktionsausdrucksyntax angegeben.

3
Roman

Die Verwendung von benannten Funktionsausdrücken ist besser, wenn Sie auf die betreffende Funktion verweisen möchten, ohne auf veraltete Funktionen wie arguments.callee zurückgreifen zu müssen.

1

Sie sollten immer NAMED-Funktionsausdrücke verwenden.

  1. Sie können den Namen dieser Funktion verwenden, wenn Sie eine Rekursion benötigen.

2.Anonymous Functions hilft beim Debuggen nicht, da der Name der Funktion, die Probleme verursacht, nicht angezeigt wird.

3.Wenn Sie eine Funktion nicht benennen, ist es später schwieriger zu verstehen, was sie tut. Wenn Sie ihr einen Namen geben, wird es leichter zu verstehen.

var foo = function bar() {
 //some code...
};
foo();
bar(); // Error!

Da beispielsweise die Namensleiste in einem Funktionsausdruck verwendet wird, wird sie nicht im äußeren Gültigkeitsbereich deklariert. Mit benannten Funktionsausdrücken ist der Name des Funktionsausdrucks in seinem eigenen Bereich eingeschlossen.

0
lux