Wild Widow Wild Widow - 6 months ago 19
jQuery Question

javascript onclick event not firing correctly

I have this click event attached to each button and when I click on each of them, it is printing the output meant for the third button. I'm not sure what is going on.

<!DOCTYPE html>
<html>
<head>
<title>JS Bin</title>
</head>
<body>
<button>test1</button>
<button>test2</button>
<button>test3</button>
</body>
<script>
var nodes = document.getElementsByTagName('button');
for (var i = 0; i < nodes.length; i++) {
nodes[i].addEventListener('click', function() {
console.log('You clicked element #' + i);
});
}
</script>
</html>


when I click on any of the buttons, it is printing

"You clicked element #3"

Answer

Simple solution to this:

<!DOCTYPE html>
<html>
<head>
  <title>JS Bin</title>
</head>
<body>
  <button>test1</button>
  <button>test2</button>
  <button>test3</button>
</body>
<script>
   var nodes = document.getElementsByTagName('button');
   console.log(nodes);
   for (var i = 0; i < nodes.length; i++) {
       //converted click function into an IIFE so it executes then and 
        there only
       nodes[i].addEventListener('click', (function(j) {
        return function(){
            console.log('You clicked element #' + j);       
        }

   })(i));
   }
</script>
</html>

You should go through two concepts to understand this thing

1) Closures

2) Javascript is single-threaded and synchronous. So how does it handle events?

Here is what it is happening in you code:

==> for loop gets executed synchronously as it is part of javascript engine post which javascript handles event queue which is a FIFO (first in first out)

==> When for loop finished value of i is three which remains in memory until the function inside it executes

==> Each time it takes a value 3 and prints it.