JavaScript Closures Cheatsheet

๐Ÿง  What Is a Closure?

  • A closure is a function that โ€œremembersโ€ variables from its outer scope
  • It retains access even after the outer function finishes
  • Enables powerful patterns like private data or dynamic functions
function outer() {
  const name = 'Alice';

  function inner() {
    console.log(name); // โœ… still has access
  }

  return inner;
}

const greet = outer();
greet(); // 'Alice'

๐Ÿ” 1. Data Privacy

  • Keep variables private inside closures
  • Great for encapsulation
  • Avoids polluting global scope
function counter() {
  let count = 0;

  return function () {
    count++;
    return count;
  };
}

const increment = counter();
increment(); // 1
increment(); // 2

๐Ÿ›  2. Function Factories

  • Create functions preset with values
  • Makes reusable logic cleaner
  • Uses closure to โ€œrememberโ€ a value
function multiplyBy(x) {
  return function (y) {
    return x * y;
  };
}

const double = multiplyBy(2);
double(5); // 10

๐Ÿ” 3. Closures in Loops (with `let`)

  • let creates a new block scope each loop iteration
  • Works perfectly with closures
  • Avoids unexpected results
for (let i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i);
  }, 1000);
}

// Prints: 0, 1, 2

โš ๏ธ Gotcha: Using `var` in Loops

  • var is function-scoped โ€” no block scope
  • All closures share the same i value
  • Leads to incorrect results in async code
for (var i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i);
  }, 1000);
}

// Prints: 3, 3, 3 โŒ

โœ… Fix It with an IIFE

  • IIFE = Immediately Invoked Function Expression
  • Captures current i value in each iteration
  • Safe way to use var with closures
for (var i = 0; i < 3; i++) {
  (function(i) {
    setTimeout(() => {
      console.log(i);
    }, 1000);
  })(i);
}

// Prints: 0, 1, 2 โœ