How it works
The explanation, with examples you can run.
Lexical scope
Scopes nest like the braces in your file. A function can read the variables of every scope around it, and nobody outside can read the ones inside it. let and const exist from the start of their block, but reading them before the line that declares them throws a ReferenceError (the "temporal dead zone"); var is hoisted to the top of the function and reads as undefined.
The loop-with-var bug
Press Run to see what your code prints, in order.
Runs in this browser, in an isolated frame with no access to this page. console.log, info, warn and error are shown; code runs as a classic script, so use an async function for await.
There is one i for the whole script, and all three arrows read it after the loop has set it to 3. A let in a for head is special: every iteration gets a fresh binding, so each arrow keeps its own j.
Private state
A closure is the simplest way to keep data private. Nothing outside counter can reach count except through the two functions it hands back.
Press Run to see what your code prints, in order.
Runs in this browser, in an isolated frame with no access to this page. console.log, info, warn and error are shown; code runs as a classic script, so use an async function for await.
The same thing explains many memory leaks: a long-lived callback that closes over a large object keeps that object alive too.
Check yourself
2 questions. Get them all right to finish this topic.
0 of 2 right so far. Get all two to finish this topic.