Kurzum
Resumen
In ihrer einfachsten Form zielt diese Technik darauf ab, den Code in eine Funktionsumfang .
Es hilft, die Chancen zu verringern:
- Kollisionen mit anderen Anwendungen/Bibliotheken
- Verschmutzungsgrad von übergeordnetem (höchstwahrscheinlich globalem) Umfang
Es nicht erkennen, wann das Dokument fertig ist - es handelt sich nicht um eine Art document.onload
noch window.onload
Es ist allgemein bekannt als ein Immediately Invoked Function Expression (IIFE)
o Self Executing Anonymous Function
.
Code erklärt
var someFunction = function(){ console.log('wagwan!'); };
(function() { /* function scope starts here */
console.log('start of IIFE');
var myNumber = 4; /* number variable declaration */
var myFunction = function(){ /* function variable declaration */
console.log('formidable!');
};
var myObject = { /* object variable declaration */
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
console.log('end of IIFE');
})(); /* function scope ends */
someFunction(); // reachable, hence works: see in the console
myFunction(); // unreachable, will throw an error, see in the console
myObject.anotherFunc(); // unreachable, will throw an error, see in the console
Im obigen Beispiel wird jede Variable, die in der Funktion definiert ist (d. h. die mit var
) sind "privat" und NUR innerhalb des Funktionsbereichs 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 Funktions-Scoping. "Parameter und Variablen, die in einer Funktion definiert sind, sind außerhalb der Funktion nicht sichtbar, und eine Variable, die irgendwo innerhalb einer Funktion definiert ist, ist überall innerhalb der Funktion sichtbar." (aus "Javascript: The Good Parts").
Mehr Details
Alternativer Code
Letztendlich könnte der zuvor gepostete Code auch wie folgt ausgeführt werden:
var someFunction = function(){ console.log('wagwan!'); };
var myMainFunction = function() {
console.log('start of IIFE');
var myNumber = 4;
var myFunction = function(){ console.log('formidable!'); };
var myObject = {
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
console.log('end of IIFE');
};
myMainFunction(); // I CALL "myMainFunction" FUNCTION HERE
someFunction(); // reachable, hence works: see in the console
myFunction(); // unreachable, will throw an error, see in the console
myObject.anotherFunc(); // unreachable, will throw an error, see in the console
Siehe Live-Demo .
Die Wurzeln
Iteration 1
Eines Tages hat sich wahrscheinlich jemand gedacht: "Es muss einen Weg geben, den Namen 'myMainFunction' zu vermeiden, denn wir wollen ja nur, dass er sofort ausgeführt wird."
Wenn man sich auf die Grundlagen besinnt, stellt man fest, dass:
expression
etwas, das zu einem Wert ausgewertet wird, d.h. 3+11/x
statement
: Codezeile(n), die etwas tun, ABER es tut no zu einem Wert auswerten, d.h. if(){}
Ähnlich verhält es sich mit Funktionsausdrücken, die einen Wert ergeben. Und eine Folge davon (nehme ich an?) ist, dass sie sofort aufgerufen werden können:
var italianSayinSomething = function(){ console.log('mamamia!'); }();
Unser komplexeres Beispiel lautet also:
var someFunction = function(){ console.log('wagwan!'); };
var myMainFunction = function() {
console.log('start of IIFE');
var myNumber = 4;
var myFunction = function(){ console.log('formidable!'); };
var myObject = {
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
console.log('end of IIFE');
}();
someFunction(); // reachable, hence works: see in the console
myFunction(); // unreachable, will throw an error, see in the console
myObject.anotherFunc(); // unreachable, will throw an error, see in the console
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, z. B. wie unten:
function(){ console.log('mamamia!'); }();
Siehe Live-Demo .
Es wird nicht funktionieren, weil "Funktionsdeklarationen sind nicht aufrufbar" .
Der Trick besteht darin, dass durch das Entfernen var myMainFunction =
haben wir die Funktionsausdruck in eine Funktionsdeklaration . Weitere Einzelheiten hierzu finden Sie unter den Links in "Ressourcen".
Die nächste Frage lautet: "Warum kann ich es nicht als Funktionsausdruck mit etwas anderem als var myMainFunction =
?
Die Antwort lautet "Sie können", und es gibt tatsächlich viele Möglichkeiten, dies zu tun: Hinzufügen einer +
, a !
, a -
oder vielleicht ein Paar Klammern (wie es heute üblich ist), und ich glaube noch mehr. Als Beispiel:
(function(){ console.log('mamamia!'); })(); // live demo: jsbin.com/zokuwodoco/1/edit?js,console.
ou
+function(){ console.log('mamamia!'); }(); // live demo: jsbin.com/wuwipiyazi/1/edit?js,console
ou
-function(){ console.log('mamamia!'); }(); // live demo: jsbin.com/wejupaheva/1/edit?js,console
Sobald wir also die entsprechende Änderung zu unserem "alternativen Code" hinzugefügt haben, erhalten wir genau denselben Code wie im Beispiel "Code erklärt"
var someFunction = function(){ console.log('wagwan!'); };
(function() {
console.log('start of IIFE');
var myNumber = 4;
var myFunction = function(){ console.log('formidable!'); };
var myObject = {
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
console.log('end of IIFE');
})();
someFunction(); // reachable, hence works: see in the console
myFunction(); // unreachable, will throw an error, see in the console
myObject.anotherFunc(); // unreachable, will throw an error, see in the console
Lesen Sie mehr über Expressions vs Statements
:
Entmystifizierung von Geltungsbereichen
Man könnte sich fragen: "Was passiert, wenn man die Variable innerhalb der Funktion NICHT 'richtig' definiert, d.h. stattdessen eine einfache Zuweisung vornimmt?"
(function() {
var myNumber = 4; /* number variable declaration */
var myFunction = function(){ /* function variable declaration */
console.log('formidable!');
};
var myObject = { /* object variable declaration */
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
myOtherFunction = function(){ /* oops, an assignment instead of a declaration */
console.log('haha. got ya!');
};
})();
myOtherFunction(); // reachable, hence works: see in the console
window.myOtherFunction(); // works in the browser, myOtherFunction is then in the global scope
myFunction(); // unreachable, will throw an error, see in the console
Siehe Live-Demo .
Wenn einer Variablen, die nicht in ihrem aktuellen Bereich deklariert wurde, ein Wert zugewiesen wird, wird grundsätzlich in der Bereichskette nachgeschaut, bis die Variable gefunden wird oder der globale Bereich erreicht wird (dann wird sie erstellt).
In einer Browserumgebung (im Gegensatz zu einer Serverumgebung wie Nodejs) wird der globale Bereich durch die window
Objekt. Wir können also tun window.myOtherFunction()
.
Mein Tipp für eine gute Praxis zu diesem Thema lautet immer verwenden var
wenn Sie etwas definieren : egal ob es sich um eine Zahl, ein Objekt oder eine Funktion handelt, und selbst wenn sie sich im globalen Bereich befinden. Das macht den Code viel einfacher.
Nota:
- Javascript macht no haben
block scope
(Aktualisierung: Lokale Variablen im Blockbereich hinzugefügt in ES6 .)
- javascript hat nur
function scope
& global scope
( window
Umfang in einer Browserumgebung)
Lesen Sie mehr über Javascript Scopes
:
Ressourcen
Nächste Schritte
Sobald Sie dies erhalten IIFE
Konzept, führt es zu dem module pattern
was in der Regel mit Hilfe dieses IIFE-Musters geschieht. Viel Spaß :)