JavaScript click handler not working as expected inside a for loop
Working DEMO
This is a classic JavaScript closure problem. Reference to the i
object is being stored in the click handler closure, rather than the actual value of i
.
Every single click handler will refer to the same object because there’s only one counter object which holds 6 so you get six on each click.
The workaround is to wrap this in an anonymous function and pass i as argument. Primitives are copied by value in function calls.
for(var i=1; i<6; i++) {
(function (i) {
$("#div" + i).click(
function () { alert(i); }
);
})(i);
}
UPDATE
Updated DEMO
Or you can use 'let' instead var
to declare i
. let
gives you fresh binding each time. It can only be used in ECMAScript 6 strict mode
.
'use strict';
for(let i=1; i<6; i++) {
$("#div" + i).click(
function () { alert(i); }
);
}
$("#div" + i).click(
function() {
alert(i);
}
);
It's because it's using the value of i
as a closure. i
is remembered through a closure which increases at every stage of the foor loop.
$("#div" + i).click(function(event) {
alert($(event.target).attr("id").replace(/div/g, ""));
});
The problem is that as you iterate through the loop, i
is incremented. It ends up with a value of 6. When you say alert(i)
you are asking javascript to tell you what the value of i
is at the time the link is clicked, which by that point is 6.
If you want to get the contents of the box instead you could do something like this:
for (var i = 1; i < 6; i++) {
console.log(i);
$("#div" + i).click(function(e) {
alert($(this).text());
});
}
div {
display: inline-block;
width: 15px;
height: 15px;
background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div id="div1">1</div>
<div id="div2">2</div>
<div id="div3">3</div>
<div id="div4">4</div>
<div id="div5">5</div>