Vorwort
In ECMascript gibt es zwei am häufigsten verwendete Methoden zum Erstellen von Funktionsobjekten, nämlich Funktionen für Funktionsausdrücke oder Verwenden von Funktionserklärungen. In dieser Hinsicht wird die Spezifikation von ECMAScript deutlich, dass Funktionserklärungen immer eine Kennung enthalten müssen, was wir den Funktionsnamen nennen, und Funktionsausdrücke können weggelassen werden. Schauen wir uns die detaillierte Einführung in die Unterschiede zwischen den beiden an.
Was ist Funktionserklärung?
Funktionserklärung kann benannte Funktionsvariablen definieren, ohne den Variablen Werte zuzuweisen. Die Funktionserklärung ist eine unabhängige Struktur, die nicht in nicht funktionsfähigen Modulen verschachtelt werden kann. Es kann mit der variablen Deklaration verglichen werden. So wie die variable Deklaration mit "var" beginnen muss, muss die Funktionserklärung mit "Funktion" beginnen.
Zum Beispiel
Funktions bar () {return 3;}ECMA 5 (13.0) Definitionssyntax:
function Identifier ( FormalParameterList[opt] ) { FunctionBody }
Funktionsnamen sind in ihrem eigenen Umfang und in ihrem übergeordneten Umfang verfügbar (ansonsten ist die Funktion nicht verfügbar).
Funktions bar () {return 3;} bar () // 3bar // FunktionWas ist Funktionsausdruck?
Der Funktionsexpression definiert eine Funktion als Teil einer Expressionsanweisung (normalerweise variable Zuordnung). Funktionen, die durch den Funktionsausdruck definiert sind, können benannt oder anonym. Der Funktionsausdruck kann nicht mit "Funktion" beginnen (die folgenden Selbstanfänger-Beispiele sollten in Klammern eingeschlossen sein).
Zum Beispiel
// Anonyme Funktion Expressionvar a = function () {return 3;} // NAME FUNKTION Expressionvar a = Funktion bar () {return 3;} // Selbstbeschaffungsfunktion Ausdruck (Funktion SayShello () {alert ("Hallo!");}) ();ECMA 5 (13.0) Definitionssyntax:
function Identifieropt ( FormalParameterList[opt] ) { FunctionBody }
(Diese Definition fühlt sich unvollständig an, weil sie eine Bedingung ignoriert: Die periphere Aussage ist ein Ausdruck und beginnt nicht mit "Funktion")
Funktionsnamen (falls vorhanden) sind außerhalb des Umfangs nicht verfügbar (im Vergleich zur Funktionserklärung).
Was ist eine Funktionserklärung?
Funktionsanweisung ist manchmal eine weitere Art der Funktionserklärung. Kangax weist jedoch darauf hin, dass in Mozilla eine Funktionserklärung eine Erweiterung der Funktionserklärung ist, mit der die Funktionserklärungserklärung überall verwendet werden kann, die die Verwendung von Anweisungen ermöglicht. Die Funktionserklärung ist jedoch jetzt nicht der Standard, daher wird nicht empfohlen, in der Produktentwicklung verwendet zu werden.
Beginnen wir mit einigen kleinen Tests. Ratet mal, was in den folgenden Situationen auftauchen wird?
Frage 1:
Funktion foo () {Funktion bar () {return 3; } return bar (); Funktions bar () {return 8; }} alert (foo ());Frage 2:
Funktion foo () {var bar = function () {return 3; }; return bar (); var bar = function () {return 8; };} alert (foo ());Frage 3:
alert (foo ()); Funktion foo () {var bar = function () {return 3; }; return bar (); var bar = function () {return 8; };}Frage 4:
Funktion foo () {return bar (); var bar = function () {return 3; }; var bar = function () {return 8; };} alert (foo ());Wenn Ihre Antwort nicht 8, 3, 3 und [Typ Fehler: Bar ist keine Funktion], dann lesen Sie weiter ... (selbst wenn Sie richtig antworten, müssen Sie weiter lesen)
Lassen Sie uns nun den vorherigen Test erklären.
Frage 1 verwendet Funktionserklärung, was bedeutet, dass sie gehoben werden ...
Warten Sie, was hebt sich?
Hier ist ein Zitat von Ben Cherry: "Funktionserklärung und Funktionsvariable werden normalerweise ('gehoben') vom JavaScript -Interpreter an die Spitze des aktuellen Bereichs verschoben."
Wenn die Funktionserklärung gefördert wird, wird die gesamte Funktionsbehörde entsprechend gefördert, so
// ** Simulierte Verarbeitungssequenz für Frage 1 ** Funktion foo () {// balkanschließend Funktionsbalken () {return 3; } // IT -Funktions bar () {return 8; } // seine Aufruf zurücksenden Return Bar (); // 8} alert (foo ());Es wird uns jedoch oft mitgeteilt, dass der Code hinter der Rückgabeerklärung nicht ausführen kann ...
Während der Ausführung von JavaScript gibt es zwei Konzepte: Kontext (ECMA 5 bricht es in Lexikalumgebungen, Variablenumgebungen und Thisbinding) und Prozess (eine Reihe von Aussagen, die in Folge bezeichnet werden). Wenn das Programm in die Ausführungsdomäne eintritt, führt die Erklärung zu einer variablen Umgebung. Sie unterscheiden sich von der Erklärung (z. B. Rückgabe) und befolgen keine Aussagen, die die laufenden Regeln befolgen.
Wird der Funktionsausdruck gefördert?
Es hängt vom Ausdruck ab. Zum Beispiel der erste Ausdruck in Frage 2:
var bar = function () {return 3;};Die (var bar) links vom gleichen Vorzeichen ist eine variable Deklaration. Die variable Erklärung wird gefördert, die Ausdrucksausdruck jedoch nicht. Wenn die Bar gefördert wird, wird der Dolmetscher so initialisiert wie folgt: var bar = undefiniert. Die Funktionsdefinition selbst wird nicht gefördert.
(ECMA 5 12.2 Variablen mit Initialzier werden durch die Zuweisungsexpression zugewiesen, wenn Variable -statement ausgeführt wird, nicht wenn die Variable erstellt wird.)
Daher wird der Code von Frage 2 in der folgenden Reihenfolge ausgeführt:
// ** Simulierte Verarbeitungssequenz für Frage 2 ** Funktion foo () {// Eine Deklaration für jeden Funktionxpression var bar bange = undefiniert; var bar = undefiniert; // Der erste Funktionsausdruck wird ausgeführt, bar = function () {return 3; }; // Funktion, die durch den ersten Funktionsexpression erstellt wurde, wird auf return bar () aufgerufen. // zweite Funktionxpression unerreichbar} alert (foo ()); // 3Sie können sagen, dass dies erklärt werden kann, aber die Antwort auf Frage 3 ist falsch. Ich werde einen Fehler beim Ausführen von Firebug melden.
Speichern Sie den Code in einer HTML -Datei und leiten Sie ihn auf Firefox aus. Oder laufen Sie in IE8, Chrome oder Safari -Konsole. Offensichtlich fördert die Firebug -Konsole die Funktion nicht, wenn der Code im "globalen" Bereich ausführt (eigentlich nicht global, sondern den einzigartigen "Firebug" -Programm - versuchen Sie einfach, in der Firebug -Konsole "This == Fenster" auszuführen).
Frage 3 und Frage 1 haben eine ähnliche Logik. Diesmal wurde die FOO -Funktion gefördert.
Frage 4 ist sehr einfach, es gibt überhaupt keine Funktionsverbesserung ...
Es kann gesagt werden, aber wenn es überhaupt keine Verbesserung gibt, wird der TypeRror "Bar nicht definiert" anstelle von "balken, keine Funktion". In diesem Beispiel gibt es in der Tat keine Funktionsverbesserung, aber es gibt eine variable Verbesserung. Daher wird die Bar zu Beginn deklariert, ihr Wert ist jedoch nicht definiert. Die anderen Codes werden in der Reihenfolge ausgeführt.
// ** Simulierte Verarbeitungssequenz für Frage 4 ** Funktion foo () {// Eine Deklaration für jeden Funktionxpression var bar bange = undefiniert; var bar = undefiniert; return bar (); // typeerrror: "bar nicht definiert" // Weder der Funktionsausdruck ist erreicht} alert (foo ());Worauf sollten Sie sonst noch darauf achten?
Der Beamte verbietet die Verwendung der Funktionserklärung in nicht funktionalen Modulen (wie IF). Alle Browser unterstützen es jedoch, aber ihre Erklärungen sind unterschiedlich.
Beispielsweise wirft der folgende Code -Snippet einen Fehler in Firefox 3.6, da es die Funktionserklärung als Funktionserklärung interpretiert (siehe oben), sodass X nicht definiert ist. In IE8, Chrome 5 und Safari 5 wird die Funktion X jedoch zurückgegeben (wie die Standardfunktionserklärung).
Funktion foo () {if (false) {Funktion x () {}; } return x;} alert (foo ());Es ist ersichtlich, dass die Verwendung der Funktionserklärung Verwirrung verursachen kann. Sie haben also Vorteile?
Sie könnten sagen, dass die Funktionserklärung ziemlich locker ist. Wenn Sie versuchen, vor der Deklaration eine Funktion zu verwenden, kann die Werbung die Reihenfolge tatsächlich korrigieren, damit die Funktion korrekt aufgerufen werden kann. Diese Art der Lockerheit ist jedoch nicht der strengen Codierung förderlich, und aus langfristiger Sicht fördert sie wahrscheinlich eher Unfälle als zu verhindern. Schließlich gibt es einen Grund, warum Programmierer Aussagen in einer bestimmten Reihenfolge anordnen.
Gibt es also andere Gründe, den Funktionsausdruck zu unterstützen?
Was denken Sie?
1) Die Funktionserklärung ist so aus, als würde sie die Erklärung im Java-Stil imitieren, aber Java-Methoden sind nicht die gleichen wie JavaScript. In JavaScript sind Funktionen lebende Objekte mit Werten. Java -Methoden sind nur die Speicherung von Metadaten. Die folgenden zwei Code -Teile definieren die Funktion, aber nur der Funktionsausdruck sieht so aus, als ob ein Objekt erstellt wird.
// Funktion deklarationFunction add (a, b) {return a + b}; // Funktion Expressionvar add = Funktion (a, b) {return a + b};2) Der Funktionsausdruck hat mehr Verwendungen. Funktionserklärung kann nur in Waisen als "Anweisung" vorhanden sein. Es kann nur eine Objektvariable unter dem aktuellen Bereich erstellen. Der Funktionsausdruck ist per Definition Teil einer großen Struktur. Wenn Sie anonyme Funktionen erstellen möchten, Prototypen Funktionen hinzufügen oder Funktionen als Eigenschaft anderer Objekte verwenden, können Sie den Funktionsausdruck verwenden. Wenn Sie erweiterte Anwendungen wie Curry oder Komponieren verwenden, verwenden Sie den Funktionsausdruck beim Erstellen neuer Funktionen. Funktionsausdruck und funktionelle Programmierung sind untrennbar miteinander verbunden.
// Funktion Expressionvar SayShello = alert.curry ("Hallo!");Gibt es Nachteile im Funktionsausdruck?
Der Funktionsausdruck erstellt die meisten Funktionen anonym. Beispielsweise ist die folgende Funktion anonym, heute ist nur ein Hinweis auf eine anonyme Funktion:
var heute = function () {return New Date ()}Wird das problematisch sein? Nicht in den meisten Fällen, aber wie Nick Fitzgerald betonte, kann es ärgerlich sein, anonyme Funktionen zu debuggen. Er empfiehlt, benannte Funktionsausdrücke (NFEs) als Arbeitsbereich zu verwenden:
var Today = Funktion Today () {Neues Datum zurückgeben ()}Wie Asen Bozhilov jedoch sagte (und Kangax -Dokumentation), können NFEs nicht korrekt unter IE9 ausgeführt werden.
abschließend
Eine zufällig platzierte Funktionserklärung ist irreführend und selten (wenn überhaupt) Situationen, und das Zuweisen von Werten an Variablen mit Funktionsausdruck kann die Funktionserklärung nicht ersetzen. Wenn jedoch eine Funktionserklärung erforderlich ist, kann die Verwirrung die Verwirrung verringern. Fügen Sie niemals Funktionserklärung in eine IF -Anweisung ein.
Trotzdem kann die Funktionserklärung in Ihrer eigenen Situation nützlich sein. Schon gut. Rollen -Dogma ist gefährlich und führt häufig dazu, dass Code um den Busch geschlagen wird. Noch wichtiger ist, dass Sie das Konzept verstehen, damit Sie entscheiden können, welche Methode die Funktion basierend auf Ihrer eigenen Situation erstellen kann. Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, dieser Artikel wird diesbezüglich für alle hilfreich sein.