0
for(let i = 0;i<buttons.length;i++){
   buttons[i].onclick = function(){
      console.log(i);
   }
}

Does JS create buttons.length scopes in global scope? Or JS only creates one scope in global?

Angel Politis
  • 10,955
  • 14
  • 48
  • 66
Shuai Li
  • 2,426
  • 4
  • 24
  • 43
  • You need to add a bit more code get a good answer, from here `buttons` seems to be a global variable – Pavlo Feb 04 '18 at 15:29
  • I this case you are making `buttons.length` different anonymous functions, each with its own scope. – mvr Feb 04 '18 at 15:29
  • 1
    Yes, for each loop iteration a new `i` is created because you are using let. if you use `var` then all the event handlers will have one reference to i and all console logs would log the length of the buttons array. – HMR Feb 04 '18 at 15:35

1 Answers1

0

The reason why using let instead of var to define i makes each button, when clicked, to log the correct i is, because let defines i inside the for loop while var defines it outside the loop.

Using let:

var buttons = document.getElementsByTagName("button");

for (let i = 0; i < buttons.length; i++) buttons[i].onclick =()=> console.log(i);
<button>0</button>
<button>1</button>
<button>2</button>

Using var:

var buttons = document.getElementsByTagName("button");

for (var i = 0; i < buttons.length; i++) buttons[i].onclick =()=> console.log(i);
<button>0</button>
<button>1</button>
<button>2</button>

Before let was introduced, one would have to come up with fancy ways to pass i inside the function, such as using an Immediately Invoked Function Expression.

Using an IIFE:

var buttons = document.getElementsByTagName("button");

for(var i = 0; i < buttons.length; i++) {
  buttons[i].onclick = (function (i) {
    return ()=> console.log(i);
  })(i);
}
<button>0</button>
<button>1</button>
<button>2</button>
Angel Politis
  • 10,955
  • 14
  • 48
  • 66