Heim  >  Artikel  >  Web-Frontend  >  Eine kurze Analyse des Unterschieds zwischen Funktionsdeklaration und Funktionsausdruck in JavaScript_Javascript-Kenntnissen

Eine kurze Analyse des Unterschieds zwischen Funktionsdeklaration und Funktionsausdruck in JavaScript_Javascript-Kenntnissen

WBOY
WBOYOriginal
2016-05-16 16:07:261020Durchsuche

Ich erinnere mich, dass mir der Interviewer diese Frage gestellt hat, als ich als Praktikant bei Tencent ein Vorstellungsgespräch geführt habe.

Code kopieren Der Code lautet wie folgt:

//Was ist der Unterschied zwischen den folgenden beiden Deklarationsmethoden

Funktion foo(){};

var bar = function foo(){}; 
Zuerst kannte ich nur zwei Deklarationsmethoden: Funktionsdeklaration und Funktionsausdruck. Die spezifischen Unterschiede konnte ich nicht erklären. Ich habe kürzlich zufällig ein Buch zu diesem Thema gesehen und wollte es zusammenfassen.

In ECMAScript gibt es zwei am häufigsten verwendete Methoden zum Erstellen von Funktionsobjekten, nämlich die Verwendung von Funktionsausdrücken oder die Verwendung von Funktionsdeklarationen. In diesem Zusammenhang macht die ECMAScript-Spezifikation deutlich, dass die Funktionsdeklaration immer einen Bezeichner (Identifier) ​​haben muss, den wir als Funktionsnamen bezeichnen, und der Funktionsausdruck weggelassen werden kann.

Funktionsdeklaration:

Code kopieren Der Code lautet wie folgt:
Funktionsbezeichner (FormalParameterList opt){ FunctionBody }

Der Analyseprozess der Funktionsdeklaration ist wie folgt:
 1. Erstellen Sie ein neues Funktionsobjekt, FormalParameterList gibt die Parameter an und FunctionBody gibt den Funktionskörper an. Verwendet die Bereichskette in der aktuell ausgeführten Umgebung als Bereich.

 2. Erstellen Sie ein Attribut namens Identifier für das aktuelle Variablenobjekt mit dem Wert Result(1).

Funktionsausdruck:

(Funktionsausdrücke werden in anonyme und benannte Funktionsausdrücke unterteilt)


Code kopieren Der Code lautet wie folgt:
Funktionsbezeichner opt(FormalParameterList opt){ FunctionBody } //Hier ist der benannte Funktionsausdruck

Der Parsing-Prozess benannter Funktionsausdrücke ist wie folgt:

1. Erstellen Sie ein neues Objekt

2. Fügen Sie Result(1) am Anfang der Bereichskette
hinzu 3. Erstellen Sie ein neues Funktionsobjekt, geben Sie die Parameter in FormalParameterList und den Funktionskörper in FunctionBody an. Verwendet die Bereichskette in der aktuell ausgeführten Ausführungsumgebung als Bereich.
4. Erstellen Sie ein Attribut mit dem Namen Identifier für Result(1), sein Wert ist Result(3), schreibgeschützt, kann nicht gelöscht werden
5. Entfernen Sie Result(1)
aus der Bereichskette 6. Ergebnis(3) zurückgeben

Die offizielle Dokumentation ist sehr schwer zu lesen. Einfach ausgedrückt unterscheidet ECMAScript die beiden durch den Kontext: Wenn die Funktion foo(){} Teil eines Zuweisungsausdrucks ist, wird sie als Funktionsausdruck betrachtet. Und wenn die Funktion foo(){} in einem Funktionskörper enthalten ist oder sich auf der obersten Ebene des Programms befindet, wird sie als Funktionsdeklaration analysiert. Wenn der Bezeichner weggelassen wird, kann der „Ausdruck“ natürlich nur ein Ausdruck sein.

Code kopieren Der Code lautet wie folgt:
function foo(){}; // Deklaration, weil es Teil des Programms ist

var bar = function foo(){}; // Ausdruck, weil es Teil des Zuweisungsausdrucks (AssignmentExpression)
ist
new function bar(){}; // Ausdruck, weil es Teil von New expression (NewExpression) ist

(function(){
Function bar(){}; // Deklaration, da sie Teil des Funktionskörpers (FunctionBody) ist
})();

Es gibt eine andere Situation:


Code kopieren Der Code lautet wie folgt:
(Funktion foo(){})

In diesem Fall handelt es sich auch um einen Funktionsausdruck, bei dem es sich um eine in Klammern eingeschlossene Funktion handelt. In seinem Kontext stellt () einen Gruppierungsoperator dar, und der Gruppierungsoperator kann nur Ausdrücke enthalten


function foo(){}; // Funktionsdeklaration

(function foo(){}); // Funktionsausdruck: Beachten Sie, dass er im Gruppierungsoperator
enthalten ist
versuche es mit {
(var x = 5); // Gruppierungsoperatoren können nur Ausdrücke enthalten, keine Anweisungen (var hier ist eine Anweisung)
}
Catch(err) {
// SyntaxError (da „var x = 5“ eine Anweisung und kein Ausdruck ist – die Auswertung eines Ausdrucks muss einen Wert zurückgeben, aber die Auswertung einer Anweisung gibt nicht unbedingt einen Wert zurück. – Übersetzung
}

Lassen Sie uns kurz über die Ähnlichkeiten und Unterschiede zwischen Funktionsdeklarationen und Funktionsausdrücken sprechen. Es gibt einen subtilen, aber wichtigen Unterschied im Verhalten von Deklarationen und Ausdrücken.

Zuerst werden Funktionsdeklarationen analysiert und ausgewertet, bevor Ausdrücke analysiert und ausgewertet werden. Auch wenn die Deklaration die letzte Zeile im Quellcode ist, wird sie vor dem ersten Ausdruck im gleichen Bereich ausgewertet. Es ist leichter zu verstehen, wenn man sich ein Beispiel anschaut. Im folgenden Beispiel wird die Funktion fn nach Alert deklariert. Wenn jedoch die Warnung ausgeführt wird, ist fn bereits definiert:

Code kopieren Der Code lautet wie folgt:

alarm(fn()); //Ausgabe Helloworld!
Funktion fn() {
return 'Helloworld!';
}

Um es kurz zusammenzufassen: Was ist der Unterschied?

1. Deklarationen werden immer am Anfang des Bereichs analysiert

2. Ausdrücke werden nur ausgewertet, wenn sie gefunden werden.

Die Funktionsdeklaration weist ein weiteres wichtiges Merkmal auf,

das heißt, das Verhalten der Steuerung der Funktionsdeklaration durch bedingte Anweisungen ist nicht standardisiert, sodass in unterschiedlichen Umgebungen unterschiedliche Ergebnisse erzielt werden können. Das heißt:

Code kopieren Der Code lautet wie folgt:
// Tu das niemals!
// Verschiedene Browser geben unterschiedliche Ergebnisse zurück,

if (true) {
Funktion foo() {
return 'first';
}
}
sonst {
Funktion foo() {
return 'second';
}
}
foo();


// Denken Sie in diesem Fall daran, Funktionsausdrücke zu verwenden:
var foo;
if (true) {
foo = function() {
return 'first';
};
}
sonst {
foo = function() {
return 'second';
};
}
foo();

Was sind also die eigentlichen Regeln für die Verwendung von Funktionsdeklarationen?

FunctionDeclaration kann nur in Program oder FunctionBody erscheinen. Syntaktisch gesehen können sie nicht innerhalb eines Blocks ({ ... }) erscheinen, beispielsweise innerhalb einer if-, while- oder for-Anweisung. Weil Block nur Statement enthalten kann, aber kein SourceElement wie FunctionDeclaration.

Wenn Sie sich andererseits die Generierungsregeln genauer ansehen, werden Sie feststellen, dass die einzige Möglichkeit für ein Ausdruck, in einem Block zu erscheinen, darin besteht, ihn zu einem Teil eines ExpressionStatements zu machen. In der Spezifikation heißt es jedoch eindeutig, dass ExpressionStatement nicht mit dem Schlüsselwort function beginnen kann. Was dies tatsächlich bedeutet, ist, dass FunctionExpression nicht in Statement oder Block erscheinen kann (vergessen Sie nicht, dass Block aus Statement besteht).

Aufgrund der oben genannten Einschränkungen sollte eine Funktion, wann immer sie in einem Block erscheint (wie im Beispiel oben), eigentlich als Syntaxfehler und nicht als Funktionsdeklaration oder Ausdruck behandelt werden.

 

 Wann sollten wir also Funktionsdeklarationen oder Funktionsausdrücke verwenden? Funktionsdeklarationen können nur im „Programmcode“ erscheinen, das heißt, sie können nur in anderen Funktionskörpern oder im globalen Raum erscheinen, ihre Definitionen können nicht einer Variablen oder einem Attribut zugewiesen oder als Parameter in einem Funktionsaufruf übergeben werden; Ein Beispiel ist die zulässige Verwendung von Funktionsdeklarationen: foo(), bar() und local() werden alle über den Funktionsdeklarationsmodus deklariert:

Code kopieren Der Code lautet wie folgt:
//Globale Umwelt
Funktion foo() {}

Funktion local() {
// Lokale Umgebung
Funktionsleiste() {}
         Rückgabeleiste;
}

Wenn Sie eine Funktionsdeklaration syntaktisch nicht verwenden können, können Sie einen Funktionsausdruck verwenden. Beispiel: Übergeben Sie eine Funktion als Parameter oder definieren Sie eine Funktion in einem Objektliteral:


Code kopieren Der Code lautet wie folgt:

// Dies ist ein anonymer Funktionsausdruck
callMe(function () {

//Eine Funktion als Parameter übergeben
});

// Dies ist ein benannter Funktionsausdruck
callMe(function me() {

// Eine Funktion als Parameter übergeben, der Funktionsname ist me
});

// Andere Funktionsausdrücke
var myobject = {
Sagen Sie: function () {

// Ich bin ein Funktionsausdruck
}
};

Mein Wissen ist begrenzt, bitte korrigieren Sie mich, wenn es Fehler gibt.

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn