Closures
In short: a closure is a function bundled together with the scope it was born in — a backpack of variables it carries along wherever it goes, even long after the outer function that created it has already returned. Every separate call to the outer function packs a separate backpack, so two functions made the same way never accidentally share state. Closures are how JavaScript gives you private variables with no special syntax at all.

A private counter, with no class needed
Each call to makeCounter creates its own count, sealed inside the
returned function:
counter1 and counter2 each close over their own count — calling
counter1() twice doesn't touch counter2's backpack at all. There's no
way to reach count directly from outside; the only access is through
the function that was handed back.
Configured functions, built once and reused
Closures are perfect for "bake in some settings, then use the result many times":
tenPercentOff and halfOff are both ordinary functions on the outside
— you just call them with a price. But each one carries its own rate in
its backpack, fixed forever at the moment it was created.
The classic trap: var in a loop
This is the single most common closure bug, and it comes down to what gets packed into the backpack:
With var, there's only one i for the whole loop — every function
packs a backpack pointing at that same shared i, which is 3 by the
time the loop ends, so every call returns 3. With let, each lap of the
loop gets its own fresh i, so each function's backpack holds a
different value: 0, 1, 2. This is one of the strongest everyday
reasons to prefer let over var.
Quick practice
What does a closure let a function keep access to, even after the outer function has returned?
In the makeDiscounter example, do tenPercentOff and halfOff share the same rate variable?
Why does the var version of the loop example return 3, 3, 3 instead of 0, 1, 2?
