Immediately Invoked Function Expressions (IIFEs) Explained

An imediately invoked function expression (IIFE), pronounced ‘iffy’, is a JavaScript design pattern often used to minimize naming conflict and create private variables.

The conventional format for an IIFE is to enclose the whole function within the grouping operator (a set of parentheses) and to leave it unnamed (i.e., anonymous). The additional set of parentheses at the end is what immediately invokes it:

(function() {
// Function contents
})();

Before we get into IIFEs at a more detailed level, let’s review the differences between function declarations and function expressions.

Function Declaration vs Function Expression

A “function declaration” (synonymous with “function statement”) requires the keyword function, a name (i.e., what follows function), and a function body (what’s between the curly braces). When a JavaScript file (or HTML document containing JavaScript) is loaded, function declarations are hoisted (moved) to the top of the code before any code is executed.

function doSomething(){
// Function contents
};

An “expression” is any valid unit of code that resolves to a value. The main difference between function declarations and function expressions is that when using function expressions, the name can be omitted, creating an anonymous function. Further, function expressions are not hoisted; the they are not loaded until the JavaScript interpreter reaches them in the script. If you try to call a function before that point, you’ll get an error.

The reason you can store an IIFE in a variable (a feature of function expressions in most contexts, one exception being callbacks [when they’re passed as a parameter to another function]) is that function expressions return a value (as all expressions do).

IIFEs Help to Minimize Naming Collisions

It’s widely considered good practice to minimize pollution of the global namespace (having many different named variables and/or functions in the global scope) to reduce the chances of naming collisions.

Defining variables inside functions or between curly braces makes them inaccessible to the global namespace. (In case you need a refresher, var [which it’s better not to use anymore] is function or global scoped, while let and const can be either global [not between curly braces] or block scoped [between curly braces].) Creating private/local scope (making variables, etc., inaccessible in global/public scope) is not a special feature of an IIFE; you could just define the variables inside a regular function as the example below demonstrates (or simply between a set of curly braces if you’re using let or const).

function exampleFunction() {
let foo = 'bar';

console.log(foo); // Outputs: 'bar'
}

exampleFunction();

console.log(foo); // ReferenceError: foo is not defined

This being said, with an IIFE, you can use an anonymous function and eliminate the chances of it being returned more than once.

(function() {
let foo = 'bar';

console.log(foo); // Outputs: 'bar'
})();

console.log(foo); // ReferenceError: foo is not defined

You can store the IIFE in a variable, since function expressions evaluate to a (function) value — whereas function declarations, being statements, don’t evaluate to anything.

const result = (function() { 
const name = 'Natalie';
return name;
})();

Does an IIFE Need Enclosing Parentheses?

If you assign the IIFE to a variable, the enclosing parentheses can be omitted:

const example = function() {
alert('IIFE success!');
}();
// Alerts "IIFE success!"

If you don’t assign the IIFE to a variable, surrounding it with parentheses is necessary for it to still work because without them, as soon as the JavaScript interpreter arrives at the function keyword, it will assume it has encountered a function declaration (resulting in an error message that a name is needed) .

function() {
alert('IIFE success!'); // ...Not
}();
// SyntaxError: function statement requires a name

But, of course, don’t add a name — that would be fulfilling the requirements for the function to be considered a function declaration, but an IIFE requires the function to be an expression (hence the word “expression”!).

If for some reason you don’t want to use enclosing parentheses, you can circumvent the need to use them by preceding the function with an exclamation point, which forces the JavaScript interpreter to treat whatever follows as an expression:

!function() {
alert('IIFE success!');
}();
// Alerts "IIFE success!"

There are other ways to force the JavaScript engine to interpret a function as a function expression:

~function () { /* ... */ }();
-function () { /* ... */ }();
+function () { /* ... */ }();
void function () { /* ... */ }();

Alternative Syntax for IIFEs

There are two ways to format an IIFE (assuming you’re using enclosing parentheses). You can use either style; it’s a matter of personal preference.

Style 1:

(function() {
// Function contents
})();

Style 2:

(function() {
// Function contents
}());

Do IIFEs Have to Be Anonymous?

IIFEs used to be called “self-invoking anonymous functions,” but the name was changed to what they’re now called in part because the word “anonymous” was deceptive (see Ben Alman’s post proposing the current name). For instance, this is perfectly acceptable:

(function namedIsFine() {
alert('Named IIFE success!');
})();

IIFEs and Closures

You can also utilize closures inside IIFEs.

In case you’re unsure what a closure is, MDN defines a closure as “a combination of a function and the lexical environment within which that function was declared.” Lexical environment...? The ES5 specification defines a lexical environment as an “association of Identifiers to specific variables and functions based upon the lexical nesting structure of ECMAScript code.” In other words, a closure is a combination of a function and its reference to its external environment (which allows it to access the contents of that environment).

Here’s an example of a closure in a regular (non-IIFE) function. (The inner function, as well as the count variable it references, comprise the closure.)

function makeCounter() {
let count = 0;
return function() {
++count;
return `count equals ${count}`;
};
};

Below is a closure in an IIFE.

let countingFunction = (function() {
let count = 0;
return function() {
++count;
return `count equals ${count}`;
};
})();

Both of these examples of closures have the benefit of preserving the value of count in subsequent function calls, whereas if a closure were not used, count would be reset to zero following each function invocation. Further, in both cases the count variable (as any let variable in a block) is private — that is, not globally accessible.

While the closure in the first (non-IIFE function) example can be called to reset the iterator whenever desired, the closure in the IIFE cannot be reset since the whole function is only run once (subsequent calls are to the function within the IIFE).

An advantage of using the IIFE version of the closure over the non-IIFE version is that you don’t have to name it (you just have to assign it to a variable in order to call it again) — or if you do name it, it won’t be visible in the global scope — so there’s one fewer item polluting the global namespace.

Here’s another example of an IIFE containing a closure:

let add = (function() {
let count = 0;
return function() {
return ++count; // Adds 1 to count
};
console.log(count);

The variable add stores the result of executing the outer function (the IIFE). It’s only executed that one first time, in which it sets count to zero and returns the function expression within it. It’s important to note the inner function is not run when the IIFE is created; it must be called before the incrementation of count executes and its result is returned.

So, once the IIFE is assigned to add, each time add() is called, the inner function is executed. This increments and returns the updated count variable. The number that appears in the console after running this code is the updated value of count returned by the inner function.

aspiring web developer | nataliecardot.com