279

I'm trying to learn JS and got an issue.

I tried many things and googled but all in vain. Following piece of code doesn't work as expected. I should get value of i on click but it always returns 6. I'm pulling my hair out; please help.

for (var i = 1; i < 6; i++) {
 console.log(i);
 $("#div" + i).click(
 function() {
 alert(i);
 }
 );
}

jsfiddle

Brian Tompsett - 汤莱恩
5,92972 gold badges63 silver badges135 bronze badges
asked May 16, 2013 at 14:13
1

3 Answers 3

163

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); }
 );
 }
answered May 16, 2013 at 14:15

Comments

41

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>

Lars Flieger
2,6891 gold badge23 silver badges61 bronze badges
answered May 16, 2013 at 14:17

Comments

19
$("#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, ""));
});
Anik Islam Abhi
25.4k8 gold badges61 silver badges82 bronze badges
answered May 16, 2013 at 14:15

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.