http://benalman.com/news/...oked-function-expression/ aka een 'iffy'

- ik ben het hier eens met Ben Alman dat 'Zelf uitvoerende anonieme functie' (self-invoking anonymous function) de lading van dit pattern niet geheel dekt
Het nut is niet beperkt tot enkel het afschermen van variabelen uit de global scope; dit 'pattern' biedt veel meer voordelen. Een paar voorbeelden:
Google analytics' async snippet:
JavaScript:
1
2
3
4
| (function(d,t){
var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
g.src='//www.google-analytics.com/ga.js';s.parentNode.insertBefore(g,s);
})(document,'script'); |
Buiten het feit dat dit niet je global scope vervuilt met de tijdelijke variabelen die gebruikt worden zie je dat je met dit pattern ook argumenten mee kan geven die er uiteindelijk voor zorgen dat de totale boilerplate van de snippet nog kleiner is
Ander voorbeeld: een interne 'state' kunnen bewaren:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| var getById = function()
{
var idCache = {};
return function(id)
{
if (!(id in idCache))
{
idCache[id] = document.getElementById(id);
}
return idCache[id];
}
}(); |
Dit lijkt niet meer geheel op het eerste voorbeeld (de haakjes om de functie expressie zijn hier ook niet nodig), en je zou mogelijk denken dat deze functie ook niet 'anonymous' meer is, maar niets is minder waar. Uiteraard had ik het ook zo kunnen schrijven:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| (function()
{
var idCache = {};
window.getById = function(id)
{
if (!(id in idCache))
{
idCache[id] = document.getElementById(id);
}
return idCache[id];
}
})(); |
En niet alleen kan je dit pattern gebruiken om interne state te bewaren zonder een instance van een object te hoeven maken, je kan er ook 'bootstrap'-logica in stoppen en afhankelijk van bepaalde condities iets anders 'exposen':
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| // just an example, don't use this in real world code!
var addEvent = function()
{
if (document.addEventListener)
{
return function(element, type, handler)
{
element.addEventListener(type, handler, false);
}
}
if (document.attachEvent)
{
return function(element, type, handler)
{
element.attachEvent('on' + evnt, func);
}
}
return function()
{
throw('What kind of browser are you using?');
}
}(); |
Voordeel hier is dat de evaluatie van welke 'branch' van de logica moet worden uitgevoerd bij het aanroepen van deze functie in een bepaalde browser maar 1 maal gedaan hoeft te worden.
En last but not least kan je dit pattern gebruiken om je eigen library eenvoudig te voorzien van een 'namespace', private vars en methods (tevens meteen een prachtig singleton-pattern):
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| var MyLibrary = function()
{
var privateVar = 'private';
function privateFunction()
{
alert('I am a private function!');
}
var publicFunction = function()
{
alert('I have access to ' + privateVar);
privateFunction();
}
return {
publicFunction: publicFunction
};
}();
MyLibrary.publicFunction(); |
edit: en Soultaker's voorbeeld van lexical scoping met behulp van dit pattern is natuurlijk ook een prachtige usecase