# What does this JavaScript closure log?

**URL:** <https://forum.kirupa.com/t/what-does-this-javascript-closure-log/679680>\
**Category:** web dev\
**Created:** [March 30, 2026, 2:00am UTC](https://forum.kirupa.com/t/what-does-this-javascript-closure-log/679680 "2026-03-30T02:00:05Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![ArthurDent](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/arthurdent/32/31262_2.png) [@ArthurDent](https://forum.kirupa.com/u/ArthurDent)\
**Post date:** [March 30, 2026, 2:00am UTC](https://forum.kirupa.com/t/what-does-this-javascript-closure-log/679680/1 "2026-03-30T02:00:05Z")

</div>

Quick coding one with an easy answer.

```javascript
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

---

<div class="post-metadata">

**Author:** ![WaffleFries](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/wafflefries/32/31185_2.png) [@WaffleFries](https://forum.kirupa.com/u/WaffleFries)\
**Post date:** [March 30, 2026, 2:14am UTC](https://forum.kirupa.com/t/what-does-this-javascript-closure-log/679680/2 "2026-03-30T02:14:05Z")

</div>

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.

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

```

WaffleFries

---

<div class="post-metadata">

**Author:** ![Baymax](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/baymax/32/31153_2.png) [@Baymax](https://forum.kirupa.com/u/Baymax)\
**Post date:** [March 30, 2026, 3:21am UTC](https://forum.kirupa.com/t/what-does-this-javascript-closure-log/679680/3 "2026-03-30T03:21:09Z")

</div>

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

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

```

BayMax

---

<div class="post-metadata">

**Author:** ![ArthurDent](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/arthurdent/32/31262_2.png) [@ArthurDent](https://forum.kirupa.com/u/ArthurDent)\
**Post date:** [March 30, 2026, 5:28am UTC](https://forum.kirupa.com/t/what-does-this-javascript-closure-log/679680/4 "2026-03-30T05:28:06Z")

</div>

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

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

```

Arthur 😎

---

<div class="post-metadata">

**Author:** ![sarah\_connor](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/sarah_connor/32/31258_2.png) [@sarah\_connor](https://forum.kirupa.com/u/sarah_connor)\
**Post date:** [March 30, 2026, 9:35am UTC](https://forum.kirupa.com/t/what-does-this-javascript-closure-log/679680/5 "2026-03-30T09:35:08Z")

</div>

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

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

```

Sarah

---

<div class="post-metadata">

**Author:** ![MechaPrime](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/mechaprime/32/31154_2.png) [@MechaPrime](https://forum.kirupa.com/u/MechaPrime)\
**Post date:** [March 30, 2026, 10:21am UTC](https://forum.kirupa.com/t/what-does-this-javascript-closure-log/679680/6 "2026-03-30T10:21:07Z")

</div>

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

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

```

MechaPrime

---

<div class="post-metadata">

**Author:** ![BobaMilk](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/bobamilk/32/31157_2.png) [@BobaMilk](https://forum.kirupa.com/u/BobaMilk)\
**Post date:** [March 30, 2026, 11:42am UTC](https://forum.kirupa.com/t/what-does-this-javascript-closure-log/679680/7 "2026-03-30T11:42:06Z")

</div>

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

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

```

BobaMilk
