11001

Closure in JavaScript

change url and proper title

A closure is a function that has access to variables in its outer (enclosing) lexical scope, even after the outer function has returned. Closures are created every time a function is created.

function outerFn() {
    const test = 'test';

    return function innerFn(){
        return test;
    }
}

const fn = outerFn();
console.log(fn());

Counter Factory

function createCounter(start = 0, step = 1) {
  let count = start;
  let history = [];
  let paused = false;
  
  // Private helper - only accessible via closure
  function validateNumber(value) {
    if (typeof value !== 'number' || isNaN(value)) {
      throw new Error('Must be a valid number');
    }
  }
  
  return {
    increment() {
      if (paused) return count;
      count += step;
      history.push({ action: 'increment', value: count });
      return count;
    },
    
    decrement() {
      if (paused) return count;
      count -= step;
      history.push({ action: 'decrement', value: count });
      return count;
    },
    
    setValue(value) {
      validateNumber(value);
      const oldCount = count;
      count = value;
      history.push({ action: 'set', from: oldCount, to: count });
      return count;
    },
    
    getValue() {
      return count;
    },
    
    pause() {
      paused = true;
    },
    
    resume() {
      paused = false;
    },
    
    reset() {
      count = start;
      history = [];
    },
    
    // Returns a new function that closes over current state
    createSnapshot() {
      const snapshot = count;
      const snapshotHistory = [...history];
      
      return {
        restore() {
          count = snapshot;
          history = snapshotHistory;
        },
        getValue() {
          return snapshot;
        }
      };
    }
  };
}

// Usage
const counter = createCounter(0, 2);
counter.increment(); // 2
counter.increment(); // 4

const snapshot = counter.createSnapshot();

counter.increment(); // 6
counter.increment(); // 8

snapshot.restore();
console.log(counter.getValue()); // 4 (restored)

Why these are complex:

  1. Multiple scope layers: Functions close over functions closing over variables

  2. Private state management: No way to access variables except through returned methods

  3. Memory persistence: State survives between function calls

  4. Method chaining: this context within closures

  5. Closure factories: Functions returning functions with captured state

  6. Event loops and timers: Closures executing asynchronously while maintaining scope

  7. Data structures: Maps, Sets, and arrays maintained across closures

  8. Circular references: Methods referencing each other through closures

React example

function Counter() {
  const [count, setCount] = useState(0);
  
  const increment = () => {
    setCount(count + 1); // Closure over 'count'
  };
  
  return <button onClick={increment}>{count}</button>;
}