Reputation: 2781
I am looking into some common Javascript programs. The following one adds 4 buttons to the DOM and adds an event listener to each of them:
for(var i =0;i<5;i++){
var btn = document.createElement('button');
btn.appendChild(document.createTextNode('Button' + i));
//function 1
(function(i){
btn.addEventListener('click', function(){console.log(i)});
})(i);
//function 2 commented
/*btn.addEventListener('click', (function(i){
return function(){
console.log(i);
}
})(i));*/
document.body.appendChild(btn);
}
both function 1 and function 2 add event listener to the buttons and work perfectly. I want to know, why the following code does not :-
for(var i =0;i<5;i++){
var btn = document.createElement('button');
btn.appendChild(document.createTextNode('Button' + i));
btn.addEventListener('click', function(){
console.log('Clicked' + i);
});
document.body.appendChild(btn);
}
This code just logs 5 for every button on click. Why is that, I do not understand why it simply does not hold the value for i for each loop?
Upvotes: 3
Views: 1272
Reputation: 50291
When addEventListener
is added to an eventTarget
while it is processing the for
loop, it does not trigger the listener.
It is triggered later stage, and at that point the for-loop
has finished it's execution and updated the value of i
.
When you are creating a function inside the for-loop
it is creating a closure and binding the value of i
Upvotes: 1
Reputation: 102174
Javascript has no block scope if you use var
. So, using exactly your code, you can have the "expected result" replacing var
for let
:
for(let i =0;i<5;i++){
var btn = document.createElement('button');
btn.appendChild(document.createTextNode('Button' + i));
btn.addEventListener('click', function(){
console.log('Clicked' + i);
});
document.body.appendChild(btn);
}
Upvotes: 2