Ich habe in letzter Zeit viel Javascript gelesen und festgestellt, dass die gesamte Datei wie folgt in die zu importierenden .js-Dateien eingeschlossen ist.
(function() {
...
code
...
})();
Was ist der Grund dafür und nicht ein einfacher Satz von Konstruktorfunktionen?
javascript
scope
coding-style
iife
Andrew Kou
quelle
quelle
Antworten:
Es dient normalerweise zum Namespace (siehe später) und zur Steuerung der Sichtbarkeit von Elementfunktionen und / oder Variablen. Stellen Sie es sich wie eine Objektdefinition vor. Der technische Name dafür ist ein sofort aufgerufener Funktionsausdruck (IIFE). jQuery-Plugins werden normalerweise so geschrieben.
In Javascript können Sie Funktionen verschachteln. Folgendes ist also legal:
Jetzt können Sie anrufen
outerFunction()
, aber die Sichtbarkeit voninnerFunction()
ist auf den Umfang von beschränktouterFunction()
, was bedeutet, dass es privat istouterFunction()
. Es folgt im Wesentlichen dem gleichen Prinzip wie Variablen in Javascript:Entsprechend:
Im obigen Szenario können Sie
globalFunction()
von überall aus anrufen , aber nichtlocalFunction1
oderlocalFunction2
.Wenn Sie schreiben
(function() { ... })()
, machen Sie den Code in den ersten Klammern zu einem Funktionsliteral (was bedeutet, dass das gesamte "Objekt" tatsächlich eine Funktion ist). Danach rufen()
Sie die gerade definierte Funktion (die letzte ) selbst auf . Der Hauptvorteil davon ist, wie ich bereits erwähnt habe, dass Sie private Methoden / Funktionen und Eigenschaften haben können:Im ersten Beispiel würden Sie explizit
globalFunction
nach Namen aufrufen , um es auszuführen. Das heißt, Sie würden es einfach tunglobalFunction()
, um es auszuführen. Im obigen Beispiel definieren Sie jedoch nicht nur eine Funktion. Sie definieren und rufen es auf einmal auf. Dies bedeutet, dass Ihre JavaScript-Datei beim Laden sofort ausgeführt wird. Natürlich können Sie Folgendes tun:Das Verhalten wäre bis auf einen wesentlichen Unterschied weitgehend dasselbe: Sie vermeiden es, den globalen Bereich zu verschmutzen, wenn Sie ein IIFE verwenden (infolgedessen bedeutet dies auch, dass Sie die Funktion nicht mehrmals aufrufen können, da sie keinen Namen hat, sondern seitdem Diese Funktion soll nur ausgeführt werden, wenn sie wirklich kein Problem darstellt.
Das Schöne an IIFEs ist, dass Sie auch Dinge innerhalb definieren und nur die Teile, die Sie möchten, der Außenwelt aussetzen können (ein Beispiel für Namespace, damit Sie im Grunde Ihre eigene Bibliothek / Ihr eigenes Plugin erstellen können):
Jetzt können Sie anrufen
myPlugin.public_function1()
, aber Sie können nicht zugreifenprivate_function()
! Also ziemlich ähnlich einer Klassendefinition. Um dies besser zu verstehen, empfehle ich die folgenden Links zur weiteren Lektüre:BEARBEITEN
Ich vergaß zu erwähnen. In diesem Finale
()
können Sie alles übergeben, was Sie wollen. Wenn Sie beispielsweise jQuery-Plugins erstellen, übergeben Sie FolgendesjQuery
oder möchten Folgendes$
:Sie definieren hier also eine Funktion, die einen Parameter akzeptiert (genannt
jQ
, eine lokale Variable, die nur dieser Funktion bekannt ist). Dann rufen Sie die Funktion selbst auf und übergeben einen Parameter (auch aufgerufenjQuery
, aber dieser stammt aus der Außenwelt und verweist auf die eigentliche jQuery selbst). Es besteht keine dringende Notwendigkeit, dies zu tun, aber es gibt einige Vorteile:Früher habe ich beschrieben, wie diese Funktionen beim Start automatisch ausgeführt werden. Wenn sie jedoch automatisch ausgeführt werden, wer übergibt die Argumente? Bei dieser Technik wird davon ausgegangen, dass alle von Ihnen benötigten Parameter bereits als globale Variablen definiert sind. Wenn jQuery nicht bereits als globale Variable definiert wäre, würde dieses Beispiel nicht funktionieren. Wie Sie vielleicht erraten haben, definiert jquery.js während der Initialisierung eine globale Variable 'jQuery' sowie die bekanntere globale Variable '$', mit der dieser Code nach dem Einfügen von jQuery funktioniert.
quelle
;(function(jQ) { ... code ... })(jQuery);
diese Weise würde jemand, der ein Semikolon in seinem Skript weggelassen hat, Ihr Semikolon nicht beschädigen, insbesondere wenn Sie vorhaben, Ihr Skript zu minimieren und mit anderen zu verketten.(function (context) { ..... })(this)
können Sie den Kontext übergeben, wodurch Sie dem übergeordneten Kontext alles hinzufügen können, was Sie möchten, und ihn so verfügbar machen.Zusamenfassend
Zusammenfassung
In ihrer einfachsten Form zielt diese Technik darauf ab, Code in einen Funktionsbereich einzubinden .
Es hilft, die Chancen zu verringern von:
Es ist nicht festzustellen , wann das Dokument fertig ist - es ist nicht irgendeine Art von
document.onload
nochwindow.onload
Es ist allgemein als
Immediately Invoked Function Expression (IIFE)
oder bekanntSelf Executing Anonymous Function
.Code erklärt
Im obigen Beispiel ist jede in der Funktion definierte Variable (dh deklariert mit
var
) "privat" und NUR innerhalb des Funktionsumfangs zugänglich (wie Vivin Paliath es ausdrückt). Mit anderen Worten, diese Variablen sind außerhalb der Funktion nicht sichtbar / erreichbar. Siehe Live-Demo .Javascript hat Funktionsumfang. "In einer Funktion definierte Parameter und Variablen sind außerhalb der Funktion nicht sichtbar, und eine an einer beliebigen Stelle innerhalb einer Funktion definierte Variable ist überall in der Funktion sichtbar." (aus "Javascript: The Good Parts").
Mehr Details
Alternativer Code
Am Ende könnte der zuvor veröffentlichte Code auch wie folgt ausgeführt werden:
Siehe Live-Demo .
Die Wurzeln
Iteration 1
Eines Tages dachte wahrscheinlich jemand: "Es muss eine Möglichkeit geben, die Benennung von 'myMainFunction' zu vermeiden, da wir sie nur sofort ausführen möchten."
Wenn Sie zu den Grundlagen zurückkehren, stellen Sie Folgendes fest:
expression
: etwas, das einen Wert ergibt. dh3+11/x
statement
: Codezeile (n), die etwas tun, ABER es wird kein Wert ausgewertet. dhif(){}
In ähnlicher Weise werden Funktionsausdrücke zu einem Wert ausgewertet. Und eine Konsequenz (nehme ich an?) Ist, dass sie sofort aufgerufen werden können:
So wird unser komplexeres Beispiel:
Siehe Live-Demo .
Iteration 2
Der nächste Schritt ist der Gedanke "Warum haben,
var myMainFunction =
wenn wir es nicht einmal benutzen!?".Die Antwort ist einfach: Versuchen Sie, dies zu entfernen, wie unten:
Siehe Live-Demo .
Es wird nicht funktionieren, weil "Funktionsdeklarationen nicht aufrufbar sind" .
Der Trick besteht darin, dass
var myMainFunction =
wir durch Entfernen den Funktionsausdruck in eine Funktionsdeklaration umgewandelt haben . Weitere Informationen hierzu finden Sie unter den Links unter "Ressourcen".Die nächste Frage lautet: "Warum kann ich es nicht als Funktionsausdruck mit etwas anderem als behalten
var myMainFunction =
?Die Antwort lautet "Sie können", und es gibt tatsächlich viele Möglichkeiten, wie Sie dies tun können: Hinzufügen von a
+
, a!
, a-
oder vielleicht in Klammern setzen (wie es jetzt durch Konvention geschieht), und mehr, glaube ich. Zum Beispiel:oder
oder
Sobald die relevante Änderung zu unserem früheren "alternativen Code" hinzugefügt wurde, kehren wir zu genau demselben Code zurück, der im Beispiel "Code Explained" verwendet wurde
Lesen Sie mehr über
Expressions vs Statements
:Bereiche entmystifizieren
Eine Sache, die man sich fragen könnte, ist: "Was passiert, wenn Sie die Variable NICHT 'richtig' innerhalb der Funktion definieren - dh stattdessen eine einfache Zuweisung vornehmen?"
Siehe Live-Demo .
Wenn einer Variablen, die nicht in ihrem aktuellen Bereich deklariert wurde, ein Wert zugewiesen wird, wird "die Bereichskette nachgeschlagen, bis sie die Variable findet oder den globalen Bereich erreicht (an welchem Punkt sie erstellt wird)".
In einer Browserumgebung (im Vergleich zu einer Serverumgebung wie nodejs) wird der globale Bereich durch das
window
Objekt definiert . Daher können wir tunwindow.myOtherFunction()
.Mein "Good Practices" -Tipp zu diesem Thema lautet: Verwenden Sie immer,
var
wenn Sie etwas definieren : ob es sich um eine Zahl, ein Objekt oder eine Funktion handelt, und selbst wenn Sie sich im globalen Bereich befinden. Dies macht den Code viel einfacher.Hinweis:
block scope
(Update: Block Umfang lokale in dem Nachspiel Variablen ES6 .)function scope
&global scope
(window
Gültigkeitsbereich in einer Browser-Umgebung)Lesen Sie mehr über
Javascript Scopes
:Ressourcen
Nächste Schritte
Sobald Sie dieses
IIFE
Konzept erhalten haben, führt es zu demmodule pattern
, was üblicherweise durch Nutzung dieses IIFE-Musters erfolgt. Habe Spaß :)quelle
Javascript in einem Browser hat wirklich nur ein paar effektive Bereiche: Funktionsumfang und globaler Bereich.
Wenn sich eine Variable nicht im Funktionsbereich befindet, befindet sie sich im globalen Bereich. Und globale Variablen sind im Allgemeinen schlecht, daher ist dies ein Konstrukt, um die Variablen einer Bibliothek für sich zu behalten.
quelle
Das nennt man eine Schließung. Grundsätzlich wird der Code innerhalb der Funktion versiegelt, damit andere Bibliotheken ihn nicht stören. Es ähnelt dem Erstellen eines Namespace in kompilierten Sprachen.
Beispiel. Angenommen, ich schreibe:
Jetzt können andere Bibliotheken nicht auf die Variable zugreifen, die
x
ich zur Verwendung in meiner Bibliothek erstellt habe.quelle
(function(){ ... return { publicProp1: 'blah' }; })();
. Offensichtlich nicht perfekt parallel zum Namespace, aber es kann hilfreich sein, dies so zu sehen.Sie können Funktionsabschlüsse auch als Daten in größeren Ausdrücken verwenden, wie bei dieser Methode zum Bestimmen der Browserunterstützung für einige der HTML5-Objekte.
quelle
Wenn Sie eine Bibliothek mit einer globalen Variablen schreiben, können Sie nicht nur die Variablen lokal halten, sondern auch einen kürzeren Variablennamen für die Bibliothek verwenden. Es wird häufig beim Schreiben von jQuery-Plugins verwendet, da Sie mit jQuery die auf jQuery verweisende Variable $ mit jQuery.noConflict () deaktivieren können. Falls es deaktiviert ist, kann Ihr Code weiterhin $ verwenden und nicht brechen, wenn Sie nur Folgendes tun:
quelle
quelle
Wir sollten auch 'use strict' in der Scope-Funktion verwenden, um sicherzustellen, dass der Code im "strict mode" ausgeführt wird. Beispielcode unten gezeigt
quelle