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.

Beispiel: 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, so dass 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.

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:

Beispiel: 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.

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, so dass auch hier ein Namenskonflikt ausgeschlossen ist.

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

Beispiel: Injektion von Abhängigkeiten in eine IIFE
(function (foo) {
    // mach was mit foo ...
})(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 etwas namens foo, das sich im die IIFE umgebenden Scope befinden muss, übergeben. Das kann eine Variable oder eine Funktion sein. Dieses foo wird in der ersten Zeile entgegengenommen und in der lokalen Variable foo abgelegt. Diese Variable kann auch anders benannt werden, jedoch verdeckt so der Parameter foo das foo im äußeren Scope, so dass man nicht versehentlich direkt darauf zugreifen kann. Absichtlich kann man beispielsweise über window.foo in den äußeren Scope zugreifen, unter der Annahme, dass der umgebende Scope der globale (also window) ist.

Es ist auch möglich, window selbst hineinzureichen. Das hat den Vorteil, dass man vielleicht für Test-Zwecke (Test wie in TDD) auch etwas anderes übergeben kann, beispielsweise einen Fake mit speziellen Eigenschaften.

Eine weitere Interaktionsmöglichkeit ist, innerhalb der IIFE ein Objekt zu konstruieren und dieses Objekt aus der IIFE zurückzugeben. Methoden dieses Objektes können auf auf Variablen zugreifen, die innerhalb der IIFE deklariert wurden, und haben damit einen privaten Speicher.

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.

Beispiel: 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[Bearbeiten]

Weblinks[Bearbeiten]