What does this JavaScript closure log?

Quick coding one with an easy answer.

for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 0);
}

What gets logged, and what tiny change would make it log 0, 1, 2.

Arthur

It logs 3, 3, 3 because var is function-scoped, so each callback reads the same final i; switch var to let and each loop gets its own binding.

for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 0);
}

WaffleFries

Yep, that let version logs 0, 1, 2, because each loop pass gets its own i.

for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 0)
}

BayMax

Yep, and the var version logs 3, 3, 3 because all three callbacks close over the same function-scoped variable.

for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 0)
}

Arthur :smiling_face_with_sunglasses:

Right, var shares one binding so by the time the timers run i is already 3, while let gives each iteration its own value.

for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 0)
}

Sarah

Exactly: var logs 3, 3, 3, while let logs 0, 1, 2 because the loop body gets a fresh binding each iteration with let.

for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 0) // 3, 3, 3
}

MechaPrime

Yes, that is right; var shares one function-scoped i, but let makes a new binding each loop turn.

for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 0) // 0, 1, 2
}

BobaMilk