IIFE & Module Scope
Running a function the instant you define it -- the pre-module way to create private scope.
(function () { /* private */ })();
(async () => { await task(); })();An Immediately Invoked Function Expression defines a function and calls it in the same breath. The wrapping parentheses turn a declaration into an expression so it can be invoked on the spot.
(function () {
// everything here is private
})();
(() => {
// arrow IIFE, same idea
})();Why it mattered, why it still appears
Before ES modules, an IIFE was the way to avoid polluting the global namespace and to build the 'module pattern' -- expose a small public object, hide everything else in the closure. You still meet it in bundled libraries, in one-off top-level scripts, and as a way to await at the top level of an old-style file.
Today
ES modules give every file its own scope for free, so new code rarely needs an IIFE. But the pattern is the clearest possible demonstration of closure-backed privacy.
Example
When to use it
- Wrap a module's initialisation code in an IIFE to avoid polluting the global scope in legacy scripts.
- Create a private variable that cannot be accessed or modified from outside the IIFE.
- Invoke an async IIFE at the top level of a module to use await without a wrapping async function.
More examples
Basic IIFE
An IIFE runs immediately and keeps its variables private; secret is inaccessible outside.
(function () {
const secret = "hidden";
console.log("IIFE ran, secret:", secret);
})();
// console.log(secret); // ReferenceErrorIIFE with return value
The IIFE computes and returns a config object while keeping internal variables private.
const config = (function () {
const env = "production";
return { env, debug: env !== "production" };
})();
console.log(config.env, config.debug); // "production" falseAsync IIFE for top-level await
Wraps async/await in an IIFE so top-level await works in environments that do not support ES modules.
(async () => {
const res = await fetch("https://jsonplaceholder.typicode.com/todos/1");
const todo = await res.json();
console.log(todo.title);
})();
Discussion