JavaScript Closures Demystified — With Practical Examples

Understand closures in JavaScript with clear explanations and real-world use cases like data privacy and memoization.

JavaScript Intermediate 📖 10 min

What Is a Closure?

A closure is a function that retains access to variables from its outer (enclosing) scope, even after the outer function has finished executing. This is one of the most powerful features in JavaScript.

Basic Closure Example

function createCounter() {
  let count = 0;
  return {
    increment: () => ++count,
    decrement: () => --count,
    getCount: () => count
  };
}

const counter = createCounter();
console.log(counter.increment()); // 1
console.log(counter.increment()); // 2
console.log(counter.getCount());  // 2

Practical Example: Function Factory

function createMultiplier(multiplier) {
  return function(number) {
    return number * multiplier;
  };
}

const double = createMultiplier(2);
const triple = createMultiplier(3);
console.log(double(5));  // 10
console.log(triple(5));  // 15

Practical Example: Memoization

function memoize(fn) {
  const cache = {};
  return function(...args) {
    const key = JSON.stringify(args);
    if (key in cache) return cache[key];
    const result = fn.apply(this, args);
    cache[key] = result;
    return result;
  };
}

const expensiveCalc = memoize((n) => {
  console.log('Computing...');
  return n * n;
});
expensiveCalc(4); // Computing... 16
expensiveCalc(4); // From cache 16

The Classic Loop Problem

// PROBLEM: All buttons log 5
for (var i = 0; i < 5; i++) {
  setTimeout(() => console.log(i), 1000);
}
// Output: 5, 5, 5, 5, 5

// SOLUTION with closure
for (var i = 0; i < 5; i++) {
  ((index) => {
    setTimeout(() => console.log(index), 1000);
  })(i);
}
// Output: 0, 1, 2, 3, 4

Closures in React Hooks

function TodoApp() {
  const [todos, setTodos] = useState([]);
  
  const addTodo = useCallback((text) => {
    setTodos(prev => [...prev, { id: Date.now(), text, done: false }]);
  }, []);

  return (
    <div>
      <button onClick={() => addTodo('New task')}>Add</button>
    </div>
  );
}

Module Pattern with Closures

const BankAccount = (function() {
  let balance = 0;
  const transactions = [];
  
  function addTransaction(type, amount) {
    transactions.push({ type, amount, date: new Date() });
  }
  
  return {
    deposit(amount) { balance += amount; addTransaction('deposit', amount); return balance; },
    withdraw(amount) { balance -= amount; addTransaction('withdrawal', amount); return balance; },
    getBalance() { return balance; },
    getTransactions() { return [...transactions]; }
  };
})();

BankAccount.deposit(1000);
BankAccount.withdraw(200);
console.log(BankAccount.getBalance()); // 800

Ready to Level Up Your Coding Skills?

Join Coderz Club and learn to code with challenges, battles, and an AI mentor.

Join Coderz Club Free →