# Pop Quiz!

Which of these is an infinite loop?

And guess many times console.log will be printed.

A: `let` 5x3 Loop

``````for(let i = 0; i < 5; i++){
for(let i = 0; i < 3; i++){
console.log(1)
}
}``````

B: `var` 5x3 Loop

``````for(var i = 0; i < 5; i++){
for(var i = 0; i < 3; i++){
console.log(1)
}
}
``````

C: `var` 5x5 Loop

``````for(var i = 0; i < 5; i++){
for(var i = 0; i < 5; i++){
console.log(1)
}
}
``````

D: `let` 5x5 Loop

``````for(let i = 0; i < 5; i++){
for(let i = 0; i < 5; i++){
console.log(1)
}
}
``````

Which of these is an infinite loop?
B: `var` 5x3

Guess many times console.log will be printed.
A: `let` 5x3 - 15 times
B: `var` 5x3 - Infinite times
C: `var` 5x5 - 5 times
D: `let` 5x5 - 25 times

Did any of the answers surprise you? I was!

# 🧐 What, but why? The difference between `let` and `var`.

< flashback >

A junior dev came up to me for help with a bug in his Javascript code that's causing a memory error, my intuition told me that there was an infinite loop somewhere.

One of the nested loops stood out as a red flag to me:

``````for(let i = 0; i < 5; i++){
for(let i = 0; i < 5; i++){
// some code
}
}
``````

I said - Hey, you're using the same variable name for outer and inner loop, this is going to cause an infinite loop.

JD: Huh? How come?

Me: Because the inner loop is reseting `i` to 0, causing the outer loop to never exit. Come let's try this in the console, it's faster to just see it.

To my surprise, there wasn't an infinite loop, we got this:

`console.log` was printed only 25 times.

Me: Hm...? That's odd. (Then I realised that the code uses `let` instead of `var`.) Maybe... the infinite loop only happens if you use `var` instead of `let`.

We changed `let` to `var`, and ran it again:

`console.log` was printed only 5 times.

Us: Wait whuut? Why it is printing only 5 times?

Me: ... Ahhh, that's because since this example uses `var` instead of `let`. `let` allows you to safely declare scoped variables with the same name. But when you use `var` to declare variables with the same name in different parent-child scopes, they all reference the same thing. So here, when you use `var`, the inner loop is sharing the same `i` as the outer loop. Meaning, when the inner loop counts `i` up to 5 and exits, the outer loop exits immediately because it's `i` counter is set to 5 by the inner loop.

JD: Ohh... okay, then what if we set the inner loop to exit when `i` is 3? I guess that produces an infinite loop?

Me: Let's find out.

`console.log` was printed way beyond 15 times, and crashed the browser.

Us: 🙌 We got an infinite loop!

And what if we change `var` to `let` now?

`console.log` was printed only 15 times.

JD: Ok, cool. But what's the use case of `var` then?

Me: Ah that's a good question. 🤔 ...none actually. There isn't a good use case for `var` now that ES6 introduced `let`. `var` is just how we used to declare variables - but then there's this problem with variables leaking out of their scope - hence `let` was proposed. Don't ask me why they decided to name the keyword `let`. And this is why our eslint is configured to enforce `let` over `var`. :)

JD: Oh! Ok... so if this loop isn't causing the memory error, so what's causing it? (That turned out to be something else altogether.)

< /flashback >

Ah thinking back, we have it good now with ES6.