An IIFE is a function expression that is defined and executed immediately. Before ES6 modules, IIFEs were the primary mechanism for creating private scope and avoiding global namespace pollution.
Wrapping a function expression in parentheses makes it an expression; the trailing () invokes it immediately
Creates a new function scope, preventing variables from leaking into the global namespace — critical before let/const
IIFE + closures create private state with a public API — the foundation of modular JS before ES6 modules
Wrapping loop body in an IIFE captures the current iteration value — solves the classic var-in-loop closure bug
An Immediately Invoked Function Expression (IIFE) is a JavaScript function that runs as soon as it is defined. The pattern wraps a function expression in parentheses to make it an expression rather than a declaration, then immediately invokes it with a trailing ().
The classic IIFE uses a regular function:
(function () {
// private scope
})();The parentheses around the function are required — without them, the parser treats function as a declaration, which requires a name. Other valid variants include (function(){})() and (function(){}()) (Douglas Crockford's preferred style). Arrow function IIFEs also work: (() => { /* code */ })().
You can pass arguments into an IIFE:
(function (global, doc) {
// Use global instead of window
})(window, document);Before ES6, JavaScript only had function scope (via var) — there was no let, const, or block scoping. The only way to create a new scope was to create a function. IIFEs solved three critical problems:
Avoiding global pollution: Variables declared inside an IIFE are not added to the global scope. Libraries like jQuery used IIFEs to avoid conflicts with other scripts.
The Module Pattern: Combining IIFEs with closures creates private variables and public APIs — the foundation of modular JavaScript before ES6 modules:
const Counter = (function () {
let count = 0; // private
return {
increment() { return ++count; },
getCount() { return count; }
};
})();var, loop variables are shared across iterations. An IIFE inside the loop captures the current value:for (var i = 0; i < 3; i++) {
(function (j) {
setTimeout(() => console.log(j), 100); // 0, 1, 2
})(i);
}This problem is now solved by let, which creates a new binding per iteration.
With ES6 modules (import/export), let/const, and block scoping, the original motivations for IIFEs are largely addressed. However, IIFEs still appear in:
<script> tags that need scope isolationKey Interview Distinction
IIFEs exist because var has function scope, not block scope. They were the only way to create private variables before let/const and ES modules. The pattern combines two concepts: function expressions (not declarations) and immediate invocation. Understanding why IIFEs were needed demonstrates deep knowledge of JavaScript's scoping history.
Fun Fact
The IIFE pattern was popularized by Ben Alman in 2010 when he coined the term in a blog post. Before that, developers called it a 'self-executing anonymous function' — but that name is technically wrong because the function doesn't execute itself, it's invoked by the trailing parentheses. Alman's article became so influential that 'IIFE' became the standard terminology used in books, documentation, and interviews.