nøkkelen til å forstå designmønstre som IIFE er å innse at Før ES6 inneholdt JavaScript bare funksjonsomfang (dermed mangler blokkomfang), passerer verdier ved referanse i lukninger. DETTE er ikke lenger tilfelle, DA ES6-versjonen av JavaScript implementerer blokkomfang ved hjelp av de nye let
og const
søkeordene.
Evaluering contextEdit
mangel på blokkomfang betyr at variabler definert i (for eksempel) a for loop vil ha sin definisjon «heist» til toppen av omsluttende funksjon. Det kan være vanskelig å vurdere en funksjon som avhenger av variabler endret av den ytre funksjonen (inkludert ved iterasjon). Vi kan se dette uten en sløyfe hvis vi oppdaterer en verdi mellom å definere og påkalle funksjonen.
var v, getValue;v = 1;getValue = function () { return v; };v = 2;getValue(); // 2
selv om resultatet kan virke innlysende når du oppdaterer v
manuelt, kan det gi utilsiktede resultater når getValue()
er definert i en sløyfe.
Heretter går funksjonen v
som et argument og påberopes umiddelbart, og bevarer den indre funksjonens utførelseskontekst.
var v, getValue;v = 1;getValue = (function (x) { return function () { return x; };})(v);v = 2;getValue(); // 1
dette tilsvarer følgende kode:
var v, getValue;v = 1;function f(x) { return function () { return x; };};getValue = f(v);v = 2;getValue(); // 1
David Hermans Effektive JavaScript inneholder et eksempel som illustrerer problemene med evalueringskontekst inne i looper. Mens Hermans eksempel er bevisst innviklet, oppstår det direkte fra samme mangel på blokkomfang.
Etablering av private variabler og tilbehørrediger
IIFEs er også nyttige for å etablere private metoder for tilgjengelige funksjoner, samtidig som de avslører noen egenskaper for senere bruk. Følgende eksempel kommer fra Alman innlegg på 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
hvis vi prøver å få tilgang tilcounter.i
fra det globale miljøet, vil det være udefinert, da det er omsluttet av den påberopte funksjonen og ikke er en egenskap av counter
. På samme måte, hvis vi prøver å få tilgang til i
, vil det resultere i en feil, da vi ikke har erklært i
i det globale miljøet.