0

I was trying creating webpage with coloured squares and wanted on clicking any square its colour should be displayed in output.

console.log() inside of addEventListener() is giving output undefined, which I expected to be rgb code as in the colors[].

While the console.log() above addEventListener() is working as expected.

I think we can't access array index of square clicked inside of addEventListener().

var colors = [
 "rgb(25, 0, 0)",
 "rgb(10, 255, 0)",
 "rgb(30, 0, 255)",
 "rgb(55, 255, 0)",
 "rgb(52, 0, 25)",
 "rgb(60, 25, 255)"
]

var squares = document.getElementsByClassName("squares");

for (var i = 0; i < colors.length; i++) {
 squares[i].style.backgroundColor = colors[i];
 console.log(colors[i]);
 squares[i].addEventListener("click",function() {
  console.log(colors[i]); // NOT WORKING AS EXPECTED
  });
}
.squares { border:1px solid grey; width:25px; height:25px; display:inline-block; }
<div id="container">
  <div class="squares"></div>
  <div class="squares"></div>
  <div class="squares"></div>
  <div class="squares"></div>
  <div class="squares"></div>
  <div class="squares"></div>
</div>
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
Optider
  • 550
  • 4
  • 11

1 Answers1

1

You are running into the classic closure use case. Change your loop variable declaration from var to let to give it block level scope and avoid the closure.

Also (just FYI), don't use getElementsByClassName() (read this for why) and instead use .querySelectorAll().

var colors = [
 "rgb(25, 0, 0)",
 "rgb(10, 255, 0)",
 "rgb(30, 0, 255)",
 "rgb(55, 255, 0)",
 "rgb(52, 0, 25)",
 "rgb(60, 25, 255)"
]

var squares = document.querySelectorAll(".squares");

for (let i = 0; i < colors.length; i++) {
 squares[i].style.backgroundColor = colors[i];
 console.log(colors[i]);
 squares[i].addEventListener("click",function() {
  console.log(colors[i]);
  });
}
.squares { border:1px solid grey; width:25px; height:25px; display:inline-block; }
<div id="container">
  <div class="squares"></div>
  <div class="squares"></div>
  <div class="squares"></div>
  <div class="squares"></div>
  <div class="squares"></div>
  <div class="squares"></div>
</div>
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
  • I got your point of the difference between var and let. When i use var, in the addEventListener the value of "i" is set to 6. Inside the for loop. As per my knowledge, the value gets incremented by 1 during each iteration.In our case 0 to 5. So, when this code is executed, then :- During 1st iteration, the value of i would be 0. And the code will become:- squares[0].addEventListener("click",function() { console.log(colors[0]); }); And this should happen with each iteration. But the value of "i" is set to 6. Could you explain why is this happening? – Optider Aug 15 '19 at 13:14
  • Because the way counting loops work is that once an iteration is done the counter is adjusted by the increment/decrement amount and then that new value is checked against the loop condition to be able to determine if the loop body should be executed again. So, after `i` is 5 and the loop runs for the 6th time, the value is incremented to 6, which is outside of the loop boundary, so the loop body is not run for a 7th time. This is true no whether you use `var` or `let`. The difference between the two has to do with the scope of the variable, not its value. – Scott Marcus Aug 16 '19 at 02:06