Immediately-Invoked Function Expression (IIFE)
In JavaScript, every
function, when invoked, creates a new execution context. Because variables and functions defined within a function may only be accessed inside, but not outside, that context, invoking a function provides a very easy way to create privacy.
In many cases, you won’t need multiple “instances” of whatever your makeWhatever function returns, and can make do with just a single instance, and in other cases, you’re not even explicitly returning a value.
The heart of the matter
Now, whether you define a function like function foo(){} or var foo = function(){}, what you end up with is an identifier for a function, that you can invoke by putting parens (parentheses, ()) after it, like foo().
JavaScript:
var foo = function(){ }
function(){ }();
As you can see, there’s a catch. When the parser encounters the function keyword in the global scope or inside a function, it treats it as a
function declaration (statement), and not as a
function expression, by default. If you don’t explicitly tell the parser to expect an expression, it sees what it thinks to be a
function declaration without a name and throws a
SyntaxError exception because function declarations require a name.
An aside: functions, parens, and SyntaxErrors
Interestingly enough, if you were to specify a name for that function and put parens immediately after it, the parser would also throw a SyntaxError, but for a different reason. While parens placed after an expression indicate that the expression is a function to be invoked, parens placed after a statement are totally separate from the preceding statment, and are simply a grouping operator (used as a means to control precedence of evaluation).
JavaScript:
function foo(){ }();
function foo(){ }( 1 );
function foo(){ }
( 1 );
Immediately-Invoked Function Expression (IIFE)
Fortunately, the SyntaxError “fix” is simple. The most widely accepted way to tell the parser to expect a function expression is just to wrap it in parens, because in JavaScript, parens can’t contain statements. At this point, when the parser encounters the function keyword, it knows to parse it as a function expression and not a function declaration.
JavaScript:
(function(){ }());
(function(){ })();
var i = function(){ return 10; }();
true && function(){ }();
0, function(){ }();
!function(){ }();
~function(){ }();
-function(){ }();
+function(){ }();
new function(){ }
new function(){ }()
An important note about those parens
In cases where the extra “disambiguation” parens surrounding the function expression are unnecessary (because the parser already expects an expression), it’s still a good idea to use them when making an assignment,
as a matter of convention.
Such parens typically indicate that the function expression will be immediately invoked, and the variable will contain the
result of the function, not the function itself. This can save someone reading your code the trouble of having to scroll down to the bottom of what might be a very long function expression to see if it has been invoked or not.
As a rule of thumb, while writing unambiguous code might be technically necessary to keep the JavaScript parser from throwing SyntaxError exceptions, writing unambiguous code is also fairly necessary to keep other developers from throwing “WTFError” exceptions at you!
Saving state with closures
Just like when arguments may be passed when functions are invoked by their named identifier, they may also be passed when immediately invoking a function expression. And because any function defined inside another function can access the outer function’s passed-in arguments and variables (this relationship is known as a closure), an
Immediately-Invoked Function Expression can be used to “lock in” values and effectively save state.