A closure is a function that retains access to variables from its outer (enclosing) scope even after that outer function has returned. Closures let functions 'remember' the environment in which they were created.
Every time a function is created, it keeps a reference to its lexical scope. When you return an inner function from an outer function, the inner function still has access to the outer function's variables — those variables are not garbage collected because the closure holds them alive. Closures power data privacy (module pattern), factory functions, memoization, and stateful callbacks. They are also the mechanism behind the classic let-vs-var loop behavior and behind currying.
A test-utility counter that generates unique IDs: function makeIdGenerator() { let n = 0; return () => `user-${++n}`; }. Each call returns user-1, user-2 ... The n variable stays private and persistent via closure — no global counter needed.
Write a function makeCounter() that returns a function; each call to the returned function increments and returns a private count that cannot be modified from outside. Explain how it works.