JavaScript Getting Started With ES2015 Defining Variables With let and const Using let with for Loops

Bass Gad
Bass Gad
Full Stack JavaScript Techdegree Student 466 Points

I didn't understand how the code runs when we use var instead of let

I didn't understand how the code runs when we use var instead of let

const buttons = document.getElementsByTagName("button");
  for(var i = 0; i < buttons.length; i++) {
      const button = buttons[i];
      button.addEventListener("click", function() {
          alert("Button " + i + " Pressed");
      });
  } 

I will explain what is my understanding so that someone can point out what is the point that I misunderstood;

Let me take the scenario where button 1 is clicked

1- In the first loop cycle when i = 0, const button = buttons[0] (first item in the array of buttons)

2- button.addEventListener will not execute since buttons[0] is not clicked

3- In the second loop cycle when i = 1 , cont button = button[1]

4- button.addEventListener will execute since the button was clicked and the alert will say "Button 1 Pressed"

5- The loop will continue until i = 10 , and const button will be assigned a new value each loop cycle but since the button was not clicked the event listener will not execute.

I am very confused and sure I am misunderstand something but can't figure it out on my own. Thanks

9 Answers

Nicholas Grenwalt
Nicholas Grenwalt
46,622 Points

The for..loop is ran as soon as the interepeter gets to it. All of the addEventListener methods will be made on each button, but like their name alludes to they will only perform the action within their callback when some event occurs. In this case they are attached to the each of the buttons made so that callback will only fire when one of those buttons is clicked. With the var keyword the value will always say 10 because they all point to the same global reference of i because the var keyword is function scoped and not block scoped. Since there is no function which var i is scoped in, just a for..loop, it becomes a global variable and keeps changing its value for all of the addEventListener methods when they finally get fired. Since let on the other hand is block scoped it lives only within the curly braces it is defined in, in this case that for loop, and each of its values for i will get set and remembered on each button's addEventListener because they no longer exist after that for loop finishes getting ran by the interpreter. Since the reference to them no longer exists, it can't be changed after it wires up the addEventListeners. But var still exists even after so all those i values become the max value of the for loop for all the buttons addEventListeners.

Aakash Srivastav
Aakash Srivastav
Full Stack JavaScript Techdegree Student 11,610 Points

You said *Since the reference to them no longer exists, it can't be changed after it wires up the addEventListeners. * , Then how will the next value will increment from that position . i,e 2 to 3 , 3 to 4 etc .
It must have refrence to 2 only then it can increment to 3 . I am confused . Please help

yoav green
yoav green
8,611 Points

you should have been the official instructor of the video! thanks alot

Nicholas Grenwalt
Nicholas Grenwalt
46,622 Points

I don't think const is causing your confusion here. It acts exactly as it should. The confusion comes with the difference between var and let. When he uses var the first go round, var variables don't have block scope (or live only in that for loop) so as you are creating all those buttons they are getting attached in all the correct places, the only difference being that the i variable is vulnerable to being changed outside that for loop. What each of those addEventListener methods have in them is a reference to that i variable. With var, when the loop increments that variable it does so globally so by the time you go to click the buttons all the event listeners have been attached pointing to that same i variable that kept getting updated each iteration through the loop so is at the value of 10. But with let, it is blocked scoped (meaning that it lives only within the block it is defined). So the i that gets attached to it as it increments will point only to that particular value of i and remember it because after it is created there is no outer reference to it globally that can change its value because it lived purely in that for..loop block, stored its value in i, and then exited.

Bass Gad
Bass Gad
Full Stack JavaScript Techdegree Student 466 Points

Thank you for your answer. Unfortunately I am not able to trace the code step by step to understand from where the issue come from. In the first place, when will this for loop be executed, it is a function that is not called. I assume it is called when I button is clicked , am I wrong. If you could please explain it on the current example by tracing the code, I think I will get it. I understood the how let and var both have different scopes but still not able to know what is the sequence of running the code step by step

Aakash Srivastav
Aakash Srivastav
Full Stack JavaScript Techdegree Student 11,610 Points

I have a doubt here with const . If the value of button is changing after every iteration i, button 0 , button 1 , then why he used const ?

Scott Craig
Scott Craig
36,811 Points

"Using let gives us DISTINCT copies of a variable upon EACH cycle of the loop.".

This is what's missing from the explanation in the video.

Nice one Anthony.

Thomas Gauperaa
Thomas Gauperaa
3,021 Points

I don't think the teacher explains this thoroughly enough, and maybe he should use a simpler example if the point is to illustrate the difference between function level and block level scope?

Brian Patterson
Brian Patterson
19,585 Points

If we had run it as a forEach loop that would have worked as well.

buttons.forEach(function(button) {
  button.addEventListener('click', function() {
    alert('Button ' + button + 'Pressed');
  });
});

This was my first thought as well.

Emanuel Rouse
Emanuel Rouse
1,985 Points

In the example he uses both var and let. Load up the workspace and use the var keyword. Open the file in the browser and then head into the console. You can see that if you lookup the i variable it will have a number of 10. However if you do the same thing with the let keyword it will be undefined. That's because var is a global and let is not. let is visible where it's defined. Meaning you can have let be either global or not it depends on how you use it. (I'm new to scope so correct me if I'm wrong.)

Rachel Heneault
Rachel Heneault
11,115 Points

This example was interesting! I will need to test it more. It's interesting the difference between using var / let in the for loops.

Roger Hwang
Roger Hwang
3,848 Points

A visual would be nice. Hard to keep track of different pieces mentally in your head.

Joshua Lee
Joshua Lee
Full Stack JavaScript Techdegree Student 2,337 Points

For anyone that struggles. Research more on global versus lexical scoping. Its a pretty good core foundation to build off of because everything we do within in Javascript is either done in the global or lexical. That was a huge understanding that I was able to grasp after reading Kyle Simpson : "Scopes and Closures" he has a whole JS series thats pretty good.