Der Schlüssel zum Verständnis von Entwurfsmustern wie IIFE besteht darin, zu erkennen, dass JavaScript vor ES6 nur den Funktionsumfang (also den fehlenden Blockumfang) enthielt und Werte als Referenz innerhalb von Verschlüssen übergab. Dies ist nicht mehr der Fall, da die ES6-Version von JavaScript das Block-Scoping mit den neuen Schlüsselwörtern let
und const
implementiert.
Evaluation contextEdit
Ein Mangel an Blockumfang bedeutet, dass Variablen, die innerhalb (zum Beispiel) einer for Schleife definiert sind, ihre Definition an die Spitze der umschließenden Funktion „gehoben“ werden. Das Auswerten einer Funktion, die von Variablen abhängt, die von der äußeren Funktion (einschließlich durch Iteration) geändert wurden, kann schwierig sein. Wir können dies ohne Schleife sehen, wenn wir einen Wert zwischen dem Definieren und Aufrufen der Funktion aktualisieren.
var v, getValue;v = 1;getValue = function () { return v; };v = 2;getValue(); // 2
Während das Ergebnis beim manuellen Aktualisieren von v
offensichtlich erscheint, kann es zu unbeabsichtigten Ergebnissen führen, wenn getValue()
in einer Schleife definiert ist.
Im Folgenden übergibt die Funktion v
als Argument und wird sofort aufgerufen, wobei der Ausführungskontext der inneren Funktion erhalten bleibt.
var v, getValue;v = 1;getValue = (function (x) { return function () { return x; };})(v);v = 2;getValue(); // 1
Dies entspricht dem folgenden Code:
var v, getValue;v = 1;function f(x) { return function () { return x; };};getValue = f(v);v = 2;getValue(); // 1
David Hermans Effektives JavaScript enthält ein Beispiel, das die Probleme des Bewertungskontexts in Schleifen veranschaulicht. Während Hermans Beispiel absichtlich verworren ist, ergibt es sich direkt aus dem gleichen Mangel an Blockumfang.
Einrichten privater Variablen und accessorsEdit
IIFEs sind auch nützlich, um private Methoden für zugängliche Funktionen einzurichten, während einige Eigenschaften für die spätere Verwendung verfügbar gemacht werden. Das folgende Beispiel stammt aus Almans Beitrag zu IIFEs.
// "counter" is a function that returns an object with properties, which in this case are functions.var counter = (function () { var i = 0; return { get: function () { return i; }, set: function (val) { i = val; }, increment: function () { return ++i; } };})();// These calls access the function properties returned by "counter".counter.get(); // 0counter.set(3);counter.increment(); // 4counter.increment(); // 5
Wenn wir versuchen, aus der globalen Umgebung auf counter.i
zuzugreifen, ist es undefiniert, da es in der aufgerufenen Funktion eingeschlossen ist und keine Eigenschaft von counter
. Wenn wir versuchen, auf i
zuzugreifen, führt dies ebenfalls zu einem Fehler, da wir i
in der globalen Umgebung nicht deklariert haben.