Closures in loops: var versus let
var k is one variable shared by all three callbacks; the loop has finished (k is 3) before any timer runs. let m gets a fresh binding each iteration. The IIFE copies n into a new parameter per call, which is how this was fixed before ES2015.
Most "what does this print?" interview questions test four rules: how hoisting sets up variables before code runs, how lexical scope decides which variable a name means, how closures keep variables alive, and how a call decides this.
Change the code and press Run (Ctrl+Enter). Predict what will happen first, then break it on purpose and read what changes. Your edits are saved and match the lesson page.
Ready for more? This phase has 6 hands-on exercises with automatic checks.
Practice questions
Write the code in the editor, run it, then open the model answer to compare.
Predict the output, then explain: var a = 1; function f() { console.log(a); var a = 2; console.log(a); } f(); console.log(a);
Predict the output: const o = { n: 1, get() { return this.n; } }; const g = o.get; console.log(o.get(), g.call({ n: 5 }), (o.get)(), (0, o.get)()); (classic sloppy script, and assume window.n is undefined).
Write once(fn) that returns a function which runs fn only the first time and returns the first result on every later call, keeping this and arguments.
Explain it without notes
Explain hoisting for var, let/const and function declarations, including the temporal dead zone.
Why does for (var i = 0; i < 3; i++) setTimeout(() => console.log(i)) print 3, 3, 3, and how do you fix it?
What is a closure? Give a real use.
List the rules that decide this, in order of priority.
Why do arrow functions behave differently with this, and when is that a problem?
Preview
Console
Nothing logged yet.Expected console output
[ 3, 3, 3 ]
[ 0, 1, 2 ]
2 1
var k: 3
var k: 3
var k: 3
let m: 0
let m: 1
let m: 2
IIFE n: 0
IIFE n: 1
IIFE n: 2