JavaScript Closures Explained: Why Your Functions Remember Everything

Published: (April 24, 2026 at 08:45 AM EDT)
2 min read
Source: Dev.to

Source: Dev.to

JavaScript Closures Explained

Closures are functions that remember variables from their outer scope, even after the outer function returns. Understanding them solves common issues like the var loop bug, stale React hooks, and memory leaks.

Key Points

  • Closures capture references, not values – functions hold pointers to variables, not snapshots.
  • Lexical scope – what a function can access is determined by where it is written in the code, not where it is called.
  • var vs let in loopsvar shares a single variable; let creates a new binding per iteration.
  • React hooks and stale closures – closures can capture old state. Fix with dependency arrays or useRef.
  • Memoization – closures can store results for performance optimization.
  • Memory leaks – closures keep references alive. Always clean up event listeners and timers.

Example: Counter

function makeCounter() {
  let count = 0; // closure keeps this alive
  return function increment() {
    count++;
    return count;
  };
}

const counter = makeCounter();
counter(); // 1
counter(); // 2
counter(); // 3

Closures allow count to persist even after makeCounter has returned.

React Stale Closure Fix

useEffect(() => {
  const id = setInterval(() => fetchResults(query), 2000);
  return () => clearInterval(id);
}, [query]); // dependency array ensures fresh state

Closures are everywhere in JavaScript; understanding them is essential to write predictable and efficient code.

0 views
Back to Blog

Related posts

Read more »