Hiprup

What are JavaScript closures with practical examples?

A closure keeps access to variables from its outer scope after that scope has returned. In practice it powers several patterns:

  • Private state — a counter that only its returned functions can change.

  • Function factories — generate preset functions, like a multiplier.

  • Memoization — keep a private cache between calls.

  • Event handlers — remember data for later, asynchronous use.

Classic bug: a var loop with setTimeout shares one variable — switch to let (or an IIFE) to capture each value.

// 1. Counter with private state
function createCounter(initial = 0) {
  let count = initial; // Private
  return {
    increment: () => ++count,
    decrement: () => --count,
    reset: () => { count = initial; },
    value: () => count
  };
}
const counter = createCounter(10);
counter.increment(); // 11
counter.increment(); // 12
// count is inaccessible directly

// 2. Once function (runs only once)
function once(fn) {
  let called = false;
  let result;
  return function(...args) {
    if (!called) {
      called = true;
      result = fn.apply(this, args);
    }
    return result;
  };
}

const initDB = once(() => {
  console.log('Connecting to DB...');
  return { connected: true };
});
initDB(); // 'Connecting to DB...' -> { connected: true }
initDB(); // Returns cached { connected: true } (no log)

// 3. Memoize
function memoize(fn) {
  const cache = new Map();
  return function(...args) {
    const key = JSON.stringify(args);
    if (cache.has(key)) return cache.get(key);
    const result = fn.apply(this, args);
    cache.set(key, result);
    return result;
  };
}

const expensiveCalc = memoize((n) => {
  console.log('Computing...');
  return n * n;
});
expensiveCalc(5); // 'Computing...' -> 25
expensiveCalc(5); // 25 (cached, no log)

Counter: count is private, accessible only through returned methods (closure). Once: called flag and result are in the closure — the function runs only on the first call, subsequent calls return the cached result.

Memoize: cache Map is in the closure — stores results by argument hash, returning cached values on repeat calls.

Show three practical closure patterns: counter (privacy), once (single execution), and memoize (caching). These demonstrate closures solving real problems, not just theory.

The once function is used for database connections, API initialization, and event handling.