Gyaan

IIFE (Immediately Invoked Function Expression)

intermediate functions scope IIFE module-pattern

An IIFE (pronounced “iffy”) is a function that runs immediately after it is defined. We do not give it a name, we do not store it in a variable — we define it and call it in one go.

Syntax

There are two common ways to write an IIFE:

// Classic function
(function() {
  console.log("I run immediately!");
})();

// Arrow function
(() => {
  console.log("I also run immediately!");
})();

The outer parentheses (function(){}) turn the function declaration into a function expression, and the trailing () immediately invokes it. Without the wrapping parentheses, JavaScript would see it as a function declaration and throw a syntax error.

We can also pass arguments to an IIFE:

(function(name) {
  console.log(`Hello, ${name}!`);
})("Manish"); // "Hello, Manish!"

Why use an IIFE?

The main reason is to avoid polluting the global scope. Any variables declared inside an IIFE are private — they cannot be accessed from outside.

(function() {
  var secret = "hidden";
  let also_secret = "also hidden";
  console.log(secret); // "hidden"
})();

// console.log(secret); // ReferenceError — not accessible

Before ES6 gave us let, const, and block scoping, IIFEs were the only way to create a private scope. With var being function-scoped, wrapping code in an IIFE was the standard way to keep variables contained.

The module pattern

One of the most common uses of IIFEs was creating modules with private state and public methods. This was the go-to pattern before ES modules existed:

const counter = (function() {
  let count = 0; // private variable

  return {
    increment() { count++; },
    decrement() { count--; },
    getCount()  { return count; }
  };
})();

counter.increment();
counter.increment();
console.log(counter.getCount()); // 2
// console.log(count); // ReferenceError — count is private

This combines IIFEs with closures — the returned object’s methods “close over” the count variable, keeping it private while exposing a clean public API.

Is IIFE still relevant?

Honestly, most of what IIFEs solved is now handled by better tools:

  • Block scopinglet and const are block-scoped, so we do not need a function wrapper just for scoping
  • Modules — ES modules (import/export) give us proper file-level scoping and dependency management
  • Bundlers — tools like Webpack and Vite handle module isolation for us

That said, IIFEs are still worth knowing for a few reasons:

  1. Interviews — they come up often, especially in the context of closures and scoping
  2. Legacy code — tons of existing JavaScript uses IIFEs
  3. Quick isolation — sometimes we still want to run a one-off block without leaking variables, and an IIFE is a clean way to do it
  4. Top-level await workaround — in environments that do not support top-level await, wrapping in an async IIFE is common:
(async () => {
  const data = await fetch("/api/data");
  const json = await data.json();
  console.log(json);
})();

In simple language, an IIFE is a function that calls itself immediately. It was a big deal before ES6, mainly for creating private scopes. Today we have better tools, but understanding IIFEs helps us read older code and answer interview questions confidently.