Disassembling JavaScript's IIFE Syntax

If you've spent even just a little time in the JavaScript world, you've likely come across the following pattern quite frequently. It's called an IIFE, which stands for immediately invoked function expression:

(function() {
    // ...
})();

A lot of the time, the function scope of an IIFE is used to prevent leaking local variables to the global scope. Similarly, IIFEs can be used to wrap state (or data in general) that's meant to be private. The basic pattern is the same in both cases.

Check out this excellent post by @toddmotto for more information on what IIFEs can be used for — better minification results, for instance!

However, you might've been wondering why we write IIFEs the way we do. They look a little odd, after all. Let's inspect the IIFE syntax and disassemble it into its parts.

The IIFE Syntax

At the heart of each IIFE is the function itself. It spans from the function keyword to the closing brace:

function() {
    // ...
}

This piece of code alone is not valid JavaScript, though. When the parser sees the function keyword at the beginning of the statement, it expects a function declaration to follow. Since the function doesn't have a name, it doesn't follow the grammar rules of a function declaration. Therefore, the parsing attempt fails and we get a syntax error.

We somehow have to make the JavaScript engine parse a function expression rather than a function declaration. If you're unsure about the difference, please refer to my post on the different kinds of function definitions in JavaScript.

The trick is quite simple, actually. We can fix the syntax error by wrapping the function within parentheses, which results in the following code:

(function() {
    // ...
})

Once the parser encounters the opening parenthesis, it expects an expression, followed by a closing parenthesis. Contrary to function declarations, function expressions don't have to be named, so the above (parenthesized) function expression is a valid piece of JavaScript code.

If you're interested in the ECMAScript language grammar, the ParenthesizedExpression production is detailed in section 12.2 of the specification.

The only part that's left now is to invoke the function expression we've just created. Right now, the function never executes because it's never called, and without being assigned to anything, there's no way of getting hold of it later. We'll add a pair of parentheses at the end:

(function() {
    // ...
})();

And here we go — that's the IIFE we've been looking for. If you think about the name for a second, it perfectly describes what we've put together: an immediately invoked function expression.

The remainder of this post gives an overview over some variations of the IIFE syntax that exist for different reasons.

Where do the parentheses go?

So far, we've been placing the parentheses that invoke the function right after the closing wrapper parenthesis:

(function() {
    // ...
})();

However, some people like Douglas Crockford famously don't like the aesthetics of a dangling pair of parentheses, so they place them within the wrapper:

(function() {
    // ...
}());

Both approaches are perfectly fine (and semantically equivalent) implementations of an immediately invoked function expression, so just pick the one you find more appealing.

Named IIFEs

The function that's being wrapped is a regular function expression, which means you can give it a name and turn it into a named function expression, if you like:

(function iife() {
    // ...
})();

Note that you still cannot leave out the wrapping parentheses around the function. This piece of code is still not valid JavaScript:

function iife() {
    // ...
}();

The parser can now successfully parse a function declaration. Immediately after it, though, it unexpectedly encounters the ( token and throws a syntax error. That's because unlike function expressions, function declarations cannot be immediately invoked.

Preventing Issues when Concatenating Files

Sometimes, you might encounter an IIFE that has a leading semicolon in front of the opening wrapping parenthesis:

;(function() {
    // ...
})();

This defensive semicolon exists to prevent issues that might arise when concatenating together two JavaScript files. Imagine the first file contains the following code:

var foo = bar

Note there's no semicolon terminating the variable declaration statement. If the second JavaScript file contained an IIFE without a leading semicolon, the concatenated result would be as follows:

var foo = bar
(function() {
    // ...
})();

This might look like an assignment of the identifier bar to the variable foo followed by an IIFE, but it's not. Instead, bar is attempted to be invoked as a function that gets passed another function as an argument. Removing the line break after bar should make the code clearer:

var foo = bar(function() {
    // ...
})();

The leading semicolon prevents this unwanted function invocation:

var foo = bar;
(function() {
    // ...
})();

Even if the leading semicolon is not preceded by any other code, it is a grammatically correct language construct. In that case, it would be parsed as an empty statement, which simply doesn't do anything and therefore does no harm.

The rules for JavaScript's automatic semicolon insertion are tricky and easily lead to unexpected errors. I recommend you always explicitly write out semicolons instead of having them inserted automatically.

Arrow Functions Instead of Function Expressions

With ECMAScript 2015, JavaScript was extended by the arrow function syntax for function definitions. Just like function expressions, arrow functions are expressions, not statements. This means that we could create an immediately invoked arrow function if we wanted to:

(() => {
    // ...
})();

Note that the wrapping parentheses around the arrow function are required for the immediate invocation to work. If you leave them out, the JavaScript parser will complain about the unexpected token ( after the closing brace. That said, I wouldn't recommend you write your IIFEs using arrow functions in the first place — I find the classic version using the function keyword much easier to read.

Use the coupon code LAUNCHDAY for $10 off!

Learn ES6

8 Comments

James Edward Lewis II

An important thing to note is that the invocation parentheses must be outside the parentheses that surround an arrow function expression, even if the body of the arrow function includes brackets; after I learned this, I used the "parentheses outside" form even for ordinary IIFEs, for consistency.

Cesar William

Good explanation of IIFEs, congrats! I think for ES6 you have more possibilities to avoid IIFEs using let, const and modules. Dr. Axel Rauschmayer shows how to avoid IIFEs in ES6 in his book: http://exploringjs.com/es6/ch_callables.html#sec_iifes-in-es6

Francis Kim

I feel much more smarter after reading this, thank you - nicely written so it was easy to understand.

Michał Załęcki

We can also use unary operator when we don't care about returning value.

!function(){ console.log("Hello")}()
nick

thanks very much. This article helps me make sense of 'Where do the parentheses go?'

Barney

If you're not keen on the punctuation soup, you can avoid the leading semi-colon and wrapping parentheses by invoking the function as new:

new function iife(){
}()
olgi3rd

Hi, May I translate your post into my website? I'll put the license what you want. Take a look my blog.