Basically, a self-executing anonymous function (more technically referred to as an IIFE or immediately invoked function expression) is the same as declaring a named function and then immediately calling it. The only difference with an IIFE is that is has no name so it can only be executed in place (not called from elsewhere) and consequently doesn't add a name to the current namespace.
So, you can use one any time that having a bunch of code inside a function would be useful and when that code only ever needs to be called in the currently defined context.
Some places where this is common:
In any kind of loop that involves some local variables and some asynchronous operations (ajax, timeout, etc...) where you want access to those local variables separately for each loop iteration in the asynchronous completion function.
To encapsulate some top level code that runs once with it's own scope and own local variables that are private and separate from the global namespace.
To create a unnamed function scope for any reason.
Examples:
Loop Index (freezes the loop index separately for each invocation of setTimeout()
):
for (var i = 0; i < max; i++) {
// capture the loop index into in a closure
(function(index) {
setTimeout(function() {
console.log(index);
}, 2000);
})(i);
}
Top Level Code Encapsulation (creates private, but persistent variable that is not in the global scope):
(function() {
var cntr = 0;
window.getUniqueId = function() {
return ++cntr;
};
})();
Create locally available shortcut variables in code that would otherwise be top level scope.
function Dictionary(initialData) {
// call parent constructor
Set.apply(this, arguments);
}
(function() {
// inherit from Set
var proto = Dictionary.prototype = new Set();
var base = Set.prototype;
// Set constructor back to us
proto.constructor = Dictionary;
// override of the base class .add()
// add(key, value)
// add(Dictionary)
// add({key1: value1, key2: value2})
proto.add = function(arg1, arg2) {
if (arg1 instanceof Set) {
// call base class to just add another Set
base.add.call(this, arg1);
} else if (typeof arg1 === "object") {
// cycle through the object and add all properties/values to the Set
for (var prop in arg1) {
if (arg1.hasOwnProperty(prop)) {
this._add(prop, arg1[prop]);
}
}
} else if (typeof arg2 !== "undefined") {
// must be add(key, value)
this._add(arg1, arg2);
}
return this;
}
proto.get = function(key) {
return this.data[key];
}
// See rest of code here: https://github.com/jfriend00/Javascript-Set/blob/master/dictionary.js
})();