IIFE

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

IIFE steht für Immediately-invoked Function Expression, also ein sofort ausgeführter Funktionsausdruck, und ist ein Idiom in der JavaScript-Programmierung.

Grundmuster
(function () {
    //...
})();

Das damit lösbare Problem ist, dass es in JavaScript keine Namensräume gibt, um verschiedene Code-Einheiten gegen andere abgrenzen zu können. Das ist besonders dann sinnvoll, wenn das Projekt größer und komplexer wird oder wenn man Bibliotheken erstellt, die neben denen anderer Hersteller eingesetzt werden sollen. Man macht sich hierbei zunutze, dass eine Funktion immer einen Scope erzeugt. Variablen und Funktionen, die in einem bestimmten Scope deklariert werden, sind außerhalb dieses Scopes nicht sichtbar, sodass der gewünschte Effekt eines privaten Raumes entsteht. Wenn innerhalb eines Scopes ein Name deklariert wird, der bereits außerhalb davon verwendet wurde, so hat die innere Deklaration Vorrang, die außerhalb deklarierte Variable oder Funktion gleichen Namens wird verdeckt.

Funktionen sind Objekte - eine Einführung

Das IIFE-Muster nutzt zusätzlich die JavaScript-Eigenschaft, dass Funktionen ganz normale Objekte sind und die Konstruktion einer Funktion ein ganz normaler Ausdruck ist, der einen Wert hat. Der Unterschied zwischen den Beispielen im Funktion-Artikel und einer IIFE ist der gleiche wie bei einer Berechnung:

Ausdrücke und Funktionen, in Variablen und direkt verwendet
// Arithmetischer Ausdruck, in einer Variablen zwischengespeichert
var x = a + 2;
alert(x);
// Arithmetischer Ausdruck, sofort verwendet
alert(a + 2);
// Funktionsausdruck, zwischengespeichert und dann aufgerufen
var t = function(x) { return x + 7; };
alert (t(3));
// Funktionsausdruck, sofort verwendet
alert( (function(x) { return x + 7; })(3));
Die Klammern um den Funktions-Ausdruck in Beispiel 4 sind notwendig, um einerseits Mehrdeutigkeiten zu vermeiden und andererseits dem JavaScript-Parser verstehen zu geben, dass der Funktionsausdruck zusammen gehört. Ohne die Klammern kann es sein, dass der JavaScript-Parser einen Fehler wirft.


Man mag einwenden, dass dieser Vergleich hinkt. Ein arithmetischer Ausdruck wird einmal ausgewertet und hat dann einen Wert, der sich nicht mehr ändert. „Ein Funktionsausdruck dagegen ist im Stande, immer wieder andere Werte zu liefern.“ Diese Formulierung stellt ein Missverständnis dar! Der Funktionsaudruck selbst liefert genau einen Wert, nämlich die anonyme Funktion. Dieser Wert bleibt unverändert. Der Wert an sich ist aber – im Gegensatz zu einem passiven Gebilde wie einer integer-Zahl – ausführbarer Code. Dieser Code liefert andere Werte, nicht der Funktionsausdruck.

Funktionen als anonyme Objekte - die IIFE

Dadurch, dass der verwendete Funktionsausdruck für eine IIFE keiner Variablen zugewiesen wird, bleibt die damit erzeugte Funktion anonym und er erzeugt keine Einträge in dem Scope, in dem er verwendet wird, sodass auch hier ein Namenskonflikt ausgeschlossen ist.

Aber wie kann man nun mit dem so geschaffenen Scope interagieren? Eine Möglichkeit ist, dass man die Abhängigkeit(en) von außen hineinreicht, also Parameter übergibt.

Injektion von Abhängigkeiten in eine IIFE
(function (wert) {
    // mach was mit wert ...
})(foo);

// Noch einmal zum Vergleich - wie sähe es mit einer nicht-anonymen Funktion aus.
var myfunc = function (foo) {
    // mach was mit foo ...
};
myfunc(foo);

In der dritten Zeile wird der Wert einer Variable namens foo, das sich im die IIFE umgebenden Scope befinden muss, übergeben. Das kann ein normaler Wert, ein Objekt oder sogar eine Funktion sein. Dieser Wert wird in der ersten Zeile im Parameter wert entgegengenommen und steht nun wie eine lokale Variable zur Verfügung. Das ist allerdings nicht besonders spannend, dafür bräuchte man keinen Funktionsscope.

Eine weitere Möglichkeit ist aber, innerhalb der anonymen Funktion ein Objekt zu konstruieren und dieses Objekt aus der IIFE zurückzugeben. Weil diese so erzeugte Funktion innerhalb der anonymen Funktion erzeugt wurde, behält sie auch nach dem Ende des IIFE-Aufrufs Zugriff auf deren lokale Variablen. Auf diese Weise entsteht ein privater Speicher, der für niemand sonst zugänglich ist.

Dieser Ansatz ist die Grundlage für das Modul-Muster. Man beachte in dem gezeigten Beispiel, dass in objektMitPrivaterVariable NICHT die anonyme Funktion gespeichert wird, sondern der von ihr zurückgegebene Wert.

IIFE, die eine Objekt zurückgibt
var objektMitPrivaterVariable = (function () {
    var geheim;
    return {
        setValue: function(v) { geheim = v; },
        showSecret: function() { alert(geheim); }
    };
})();

objektMitPrivaterVariable.setValue(4711);
var xx = objektMitPrivaterVariable.geheim;       // Geht nicht, geheim ist keine Eigenschaft des Objekts

Dieses Vorgehen mag verwirrend erscheinen. Nachdem die IIFE ausgeführt wurde, existiert keine Referenz mehr auf die verwendete anonyme Funktion und sie kann dadurch vom Garbage Collector abgeräumt werden. Normalerweise würden dadurch auch alle Variablen beseitigt, die in dem Scope angelegt wurden, der zu dieser Funktion gehört. Im Beispiel kommt aber ein weiterer Effekt ins Spiel. Die IIFE gibt ein Objekt zurück, das mittels seiner Methoden den Scope der anonymen Funktion referenziert. Das führt dazu, dass der Scope der anonyme Funktion erhalten bleibt und erst von der Garbage Collection abgeräumt wird, wenn auch das zurückgegebene Objekt nicht mehr referenziert wird. Dieses Konstrukt nennt man ein Closure.

Siehe auch

Weblinks