JavaScript: Closures (In-Depth)

A closure is a feature of JavaScript where an inner function has access to the variables and parameters of its outer function, even after the outer function has finished executing. Closures are essential for maintaining private state, creating function factories, and asynchronous programming.

What is a Closure?

When a function is declared inside another function, the inner function forms a closure. This means it "remembers" the environment in which it was created.

Closure Example

function makeCounter() {
  let count = 0;
  return function() {
    count++;
    return count;
  };
}
const counter = makeCounter();
counter(); // 1
counter(); // 2
    
// Output:
1
2

How Closures Work

const anotherCounter = makeCounter();
anotherCounter(); // 1 (separate count!)
    

Closures and Private Data

Closures enable data privacy by keeping variables hidden from the outside world.

function secretHolder(secret) {
  return {
    getSecret: function() { return secret; },
    setSecret: function(val) { secret = val; }
  };
}
const holder = secretHolder("hidden");
holder.getSecret(); // "hidden"
holder.setSecret("new secret");
holder.getSecret(); // "new secret"
    

Closures in Loops

Be careful with closures inside loops! Each closure captures the variable, not its value at the time.

var funcs = [];
for (var i = 0; i < 3; i++) {
  funcs.push(function() { return i; });
}
funcs[0](); // 3, not 0!
    
Solution: Use let in ES6, or an IIFE to capture values correctly.
let funcs = [];
for (let i = 0; i < 3; i++) {
  funcs.push(function() { return i; });
}
funcs[0](); // 0
    

Use Cases for Closures

Summary

Practice: Try creating counters, private data holders, and custom event handlers with closures to master this concept.