de sleutel tot het begrijpen van ontwerppatronen zoals IIFE is om te beseffen dat vóór ES6, JavaScript alleen functie scope (dus ontbreekt blok scope), het passeren van waarden door verwijzing binnen sluitingen. Dit is niet langer het geval, aangezien de ES6-versie van JavaScript block scoping implementeert met behulp van de nieuwe let
en const
sleutelwoorden.
evaluatie contextEdit
een gebrek aan block scope betekent dat variabelen gedefinieerd in (bijvoorbeeld) A Voor loop hun definitie “hoisted” naar de bovenkant van de enclosing functie. Het evalueren van een functie die afhankelijk is van variabelen gewijzigd door de buitenste functie (inclusief door iteratie) kan moeilijk zijn. We kunnen dit zien zonder een lus als we een waarde tussen het definiëren en aanroepen van de functie bijwerken.
var v, getValue;v = 1;getValue = function () { return v; };v = 2;getValue(); // 2
hoewel het resultaat duidelijk lijkt wanneer v
handmatig wordt bijgewerkt, kan het onbedoelde resultaten opleveren wanneergetValue()
binnen een lus is gedefinieerd.
hierna geeft de functie v
als argument en wordt onmiddellijk aangeroepen, waarbij de uitvoercontext van de interne functie behouden blijft.
var v, getValue;v = 1;getValue = (function (x) { return function () { return x; };})(v);v = 2;getValue(); // 1
Dit is gelijk aan de volgende code:
var v, getValue;v = 1;function f(x) { return function () { return x; };};getValue = f(v);v = 2;getValue(); // 1
David Herman ‘ s effectieve JavaScript bevat een voorbeeld dat de problemen van evaluatiecontext in lussen illustreert. Terwijl Herman ‘ s voorbeeld opzettelijk ingewikkeld is, komt het rechtstreeks voort uit hetzelfde gebrek aan Block scope.
het instellen van private variabelen en accessorsEdit
IIFEs zijn ook nuttig voor het instellen van private methoden voor toegankelijke functies, terwijl sommige eigenschappen nog steeds worden blootgelegd voor later gebruik. Het volgende voorbeeld komt uit Alman ‘ s post op 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
als we proberen toegang te krijgen tot counter.i
vanuit de globale omgeving, zal het niet gedefinieerd zijn, omdat het is ingesloten in de aangeroepen functie en geen eigenschap is van counter
. Evenzo, als we proberen toegang te krijgen tot i
, zal dit resulteren in een fout, omdat we i
niet hebben gedeclareerd in de globale omgeving.