512 Stimmen

Was ist der Unterschied zwischen einem Funktionsausdruck und einer Deklaration in JavaScript?

Was ist der Unterschied zwischen den folgenden Codezeilen?

//Function declaration
function foo() { return 5; }

//Anonymous function expression
var foo = function() { return 5; }

//Named function expression
var foo = function foo() { return 5; }
  • Was ist ein benannter/anonymer Funktionsausdruck?
  • Was ist eine erklärte Funktion?
  • Wie gehen die Browser mit diesen Konstrukten unterschiedlich um?

Wie lauten die Antworten auf eine ähnliche Frage ( var Funktionsname = function() {} vs function Funktionsname() {} ) nicht genau richtig hinbekommen?

430voto

Khon Lieu Punkte 4245

Sie sind sich tatsächlich sehr ähnlich. Der Unterschied liegt in der Art und Weise, wie der Browser sie in den Ausführungskontext lädt.

Funktionsdeklarationen werden geladen, bevor der Code ausgeführt wird.

Funktionsausdrücke werden erst dann geladen, wenn der Interpreter diese Codezeile erreicht.

Wenn Sie also versuchen, einen Funktionsausdruck aufzurufen, bevor er geladen ist, erhalten Sie eine Fehlermeldung! Wenn Sie stattdessen eine Funktionsdeklaration aufrufen, funktioniert das immer, weil kein Code aufgerufen werden kann, bevor nicht alle Deklarationen geladen sind.

Beispiel: Funktionsausdruck

alert(foo()); // ERROR! foo wasn't loaded yet
var foo = function() { return 5; } 

Beispiel: Funktionsdeklaration

alert(foo()); // Alerts 5. Declarations are loaded before any code can run.
function foo() { return 5; } 

Was den zweiten Teil Ihrer Frage betrifft:

var foo = function foo() { return 5; } ist eigentlich dasselbe wie die beiden anderen. Es ist nur, dass diese Zeile des Codes verwendet, um einen Fehler in Safari verursachen, obwohl es nicht mehr tut.

113voto

geniuscarrier Punkte 4079

Funktionserklärung

function foo() { ... }

Wegen der Funktion Heben kann die auf diese Weise deklarierte Funktion sowohl nach als auch vor der Definition aufgerufen werden.

Funktion Ausdruck

  1. Benannter Funktionsausdruck

    var foo = function bar() { ... }
  2. Anonymer Funktionsausdruck

    var foo = function() { ... }

foo() kann erst nach der Erstellung aufgerufen werden.

Unmittelbar ausgelöster Funktionsausdruck (IIFE)

(function() { ... }());

Schlussfolgerung

Crockford empfiehlt die Verwendung von Funktionsausdrücken, weil sie deutlich machen, dass foo ist eine Variable, die einen Funktionswert enthält. Ich persönlich ziehe es vor, Declaration zu verwenden, es sei denn, es gibt einen Grund für Expression.

21voto

TomTom Punkte 1747

Bezüglich der 3. Definition:

var foo = function foo() { return 5; }

Hier ein Beispiel, das zeigt, wie man die Möglichkeit des rekursiven Aufrufs nutzen kann:

a = function b(i) { 
  if (i>10) {
    return i;
  }
  else {
    return b(++i);
  }
}

console.log(a(5));  // outputs 11
console.log(a(10)); // outputs 11
console.log(a(11)); // outputs 11
console.log(a(15)); // outputs 15

Bearbeiten: Interessanteres Beispiel mit Verschlüssen:

a = function(c) {
 return function b(i){
  if (i>c) {
   return i;
  }
  return b(++i);
 }
}
d = a(5);
console.log(d(3)); // outputs 6
console.log(d(8)); // outputs 8

13voto

Alex Punkte 32100

Die erste Aussage hängt von dem Kontext ab, in dem sie deklariert wird.

Wenn sie im globalen Kontext deklariert wird, wird eine implizite globale Variable namens "foo" erstellt, die auf die Funktion verweist. So kann der Funktionsaufruf "foo()" überall in Ihrem Javascript-Programm erfolgen.

Wenn die Funktion in einem Closure erstellt wird, wird eine implizite lokale Variable namens "foo" erstellt, die Sie dann verwenden können, um die Funktion innerhalb des Closures mit "foo()" aufzurufen.

EDIT:

Ich hätte auch sagen sollen, dass Funktionsanweisungen (die erste) vor Funktionsausdrücken (die anderen 2) geparst werden. Das heißt, wenn Sie die Funktion am Ende Ihres Skripts deklarieren, können Sie sie trotzdem am Anfang verwenden. Funktionsausdrücke werden erst ausgewertet, wenn sie vom ausführenden Code getroffen werden.

ENDE BEARBEITEN

Die Aussagen 2 und 3 sind so ziemlich gleichwertig. Wenn sie im globalen Kontext verwendet werden, erzeugen sie globale Variablen, und wenn sie innerhalb einer Schließung verwendet werden, erzeugen sie lokale Variablen. Es ist jedoch erwähnenswert, dass Anweisung 3 den Funktionsnamen ignoriert, so dass Sie die Funktion im Grunde genommen beliebig aufrufen können. Daher

var foo = function foo() { return 5; }

Ist dasselbe wie

var foo = function fooYou() { return 5; }

1voto

Jake Punkte 538

Obwohl der gesamte Unterschied komplizierter ist, ist der einzige Unterschied, der mich betrifft, der Zeitpunkt, zu dem die Maschine das Funktionsobjekt erstellt. Im Falle von Deklarationen ist das, bevor eine Anweisung ausgeführt wird, aber nachdem ein Anweisungskörper aufgerufen wurde (sei es der globale Codekörper oder der einer Unterfunktion), und im Falle von Ausdrücken, wenn die Anweisung, in der sie enthalten ist, ausgeführt wird. Abgesehen davon werden sie von den Browsern in jeder Hinsicht gleich behandelt.

Um das zu verstehen, sehen Sie sich diese Leistung an Test was eine Annahme zerstörte, die ich in Bezug auf intern deklarierte Funktionen gemacht hatte, die von der Maschine nicht neu erstellt werden müssen, wenn die äußere Funktion aufgerufen wird. Irgendwie schade, denn ich habe den Code gerne auf diese Weise geschrieben.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X