By the end of this lesson, you will be able to write an immediately-invoked function expression (IIFE) in JavaScript to run code once and keep variables out of the global scope.
What it is
An IIFE is a function expression that is called as soon as it is defined. The key idea is that JavaScript only allows a function to be invoked immediately when it appears as an expression, not as a standalone function declaration. Wrapping the function in parentheses turns it into an expression, and the trailing parentheses call it.
Related terms: function expression, anonymous function, scope, module pattern, private variables.
Why it matters
- It creates a private scope for variables, reducing accidental global pollution.
- It lets you run setup code once without leaving helper variables behind.
- It was historically used to build simple modules before ES modules became common.
- It can avoid variable hoisting problems in older code by isolating declarations.
- It is useful in scripts, browser snippets, and legacy code where a small self-contained block is needed.
Syntax or steps
The smallest useful pattern is:
(function () {
// code here
})();
Step by step:
- Write
function () { ... }as an expression. - Wrap it in parentheses:
(function () { ... }). - Add another pair of parentheses after it to invoke it:
(function () { ... })().
Arrow functions can also be IIFEs: (() => { ... })();.
Example
(function () {
const message = "runs once";
let count = 0;
function increment() {
count += 1;
console.log(message, count);
}
increment();
increment();
})();
console.log(typeof message); // undefined
Part-by-part explanation:
(function () { ... })is a function expression.()at the end immediately calls it.messageandcountexist only inside the IIFE.- The final
console.log(typeof message)shows thatmessageis not available outside.
Common mistakes
- Forgetting the outer parentheses:
function () { ... }();is invalid because a function declaration cannot be invoked that way. Fix: wrap it as(function () { ... })();. - Forgetting the invocation parentheses:
(function () { ... });defines but does not run. Fix: add()after the closing parenthesis. - Relying on automatic semicolon insertion when the previous statement lacks a semicolon. Fix: end the previous statement with
;or start the IIFE with;. - Using an IIFE when a normal function or ES module would be clearer. Fix: prefer named functions or modules when the code needs to be reused or imported.
When to use it
Compare IIFE with block scope and ES modules:
| Pattern | Best for | Limitation |
|---|---|---|
| IIFE | One-time setup, legacy scripts, quick private scope | Can be less readable if overused |
let/const block |
Simple local variables in modern JavaScript | Does not create a reusable function boundary |
| ES module | Organized, importable code in modern projects | Requires module loading and tooling support |
Use an IIFE when you need a small, self-contained piece of code that runs immediately and should not expose its internals. Use a block when you only need local variables. Use an ES module when the code should be shared, imported, or maintained as part of a larger application.
Practice
Guided exercise: write an IIFE that creates a private variable called secret, logs it once, and then tries to log it outside the IIFE.
(function () {
const secret = "hidden";
console.log(secret);
})();
console.log(secret); // ReferenceError
Challenge: modify the IIFE so it accepts a name parameter and logs Hello, Ada! exactly once.
Solution hint: put the parameter inside the function parentheses and the argument inside the invocation parentheses.
(function (name) {
console.log("Hello, " + name + "!");
})("Ada");
Quick check
Question: Why must an IIFE be written as a function expression rather than a function declaration?
Answer: JavaScript only allows an expression to be immediately invoked. A function declaration is a statement, so it cannot be called directly with trailing parentheses unless it is wrapped or otherwise turned into an expression.
Summary
An IIFE is a function expression that runs immediately, creating a private scope for variables and one-time setup code. It is most useful in scripts and legacy patterns, while modern code often prefers block scope or ES modules for clarity.