Not understanding the alert() in the for loop

I’m on this page discussing the while and for loops:

<!DOCTYPE html>
<script>
"use strict";

let i = 0;

for (i = 0; i < 3; i++) { // use an existing variable
  alert(i); // 0, 1, 2
}

alert(i); // 3, visible, because declared outside of the loop
</script>

I don’t understand why the final alert(i) shows 3, since it is outside the curly braces. Isn’t it the same as being outside a function?

@WebSteve notice for (i = 0; is not for (let i = 0. It’s using the ‘i’ declared outside of the loop.

A similar example with a function

let i = 0

// The function doesn't have a locally declared 'i' so looks up the
// scope chain to the globally declared one above. 
function increment() { 
  i = 0;
  i += 3;
} 

increment()

alert(i) // 3

And a function with a locally declared variable

let i = 0

function increment() { 
  let i = 0;
  i += 3;
} 

increment()

alert(i) // 0

So in this one, we are declaring the variable.
Then we call the function at increment().
Then the function cycles through and when done, we jump out of the function.
Then the alert(i) returns the result.

And if it helps to understand things further, the order that those lines are executed in is as as follows:

  1. let i = 0;
  2. increment()
  3. i = 0;
  4. i += 3;
  5. alert(i)
1 Like

Would just change the alert(i) line to ‘outputs the result’, but yes sounds good to me :slight_smile:

Here’s what I don’t understand. Since JS is run from top to bottom, why doesn’t the position of increment() immediately after the function cause the script to form an endless loop? Why does function increment() execute and then jump the increment() call and go right to the alert?

The only thing I can think of is that the function is happening in the place of the call to the function.

Because functions are not executed when they are defined. Only when they are called.

1 Like

And they are executed in the place where they are called, not earlier. Then the script continues from there.

Hi @WebSteve,

I would recommend you have a look at hoisting.

I have tried to break down the thread of execution with the following diagram.

You can think of the increment function as being a separate script that before execution is set aside. I have illustrated that with the global object. You can also see it has an i, which is yet to be initialised (no value). This process is referred to as hoisting.

Thread of execution

  1. i is given a value of 0
  2. The function increment is invoked.
  3. The function increment had no i of it’s own, sources it via the scope chain finding it in the global object, and again sets it’s value to 0
  4. step 3 is repeated, but this time i is increased by 3
  5. The function increment returns.
  6. The alert function is invoked passing in the value of i

I hope this helps.

edit: (hoisting not hoisiting)

Lexical Environment

The breakdown I gave above is incorrect and it’s been bugging me. Specifically with regards let declaring a variable on the global object. Had it been var that would have been the case, but not with let or const.

var x = 5;
let y = 10;
console.log(window.x) // 5
console.log(window.y) // undefined

Instead of me trying to interpret the official ECMAScript docs into plain English, for those interested here is a more manageable read.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.