Sticky/static variable references in for loops
In this example I create three buttons 'one' 'two' 'three'. When clicked I want them to alert their number:
<html>
<head>
<script type="application/javascript" src="jquery.js"></script>
<script type="application/javascript">
$(document).ready(function() {
var numbers = ['one', 'two', 'three'];
for (i in numbers) {
var nr = numbers[i];
var li = $('<li>' + nr + '</li>');
li.click(function() {
var newVariable = String(nr);
alert(i); // 2
alert(nr); // three
开发者_JS百科 alert(newVariable); // three
alert(li.html()); // three
});
$('ul').append(li);
}
});
</script>
</head>
<body>
<ul>
</ul>
</body>
</html>
The problem is, when any of these are clicked, the last value of the loop's variables is used, i.e. alert box always says 'three'.
In JavaScript, variables inside for-loops seem to be 'static' in the C language sense. Is there some way to create separate variables for each click function, i.e. not using the same reference?
Thanks!
Edit:
The solution is to use jQuery.data to associate arbitrary data with each element:
<html>
<head>
<script type="application/javascript" src="jquery.js"></script>
<script type="application/javascript">
$(document).ready(function() {
var numbers = ['one', 'two', 'three'];
for (i in numbers) {
var nr = numbers[i];
var li = $('<li>' + nr + '</li>');
li.data('nr', nr);
li.click(function() {
alert($(this).data('nr'));
});
$('ul').append(li);
}
});
</script>
</head>
<body>
<ul>
</ul>
</body>
</html>
Alternately, place a closure inside the for loop.
$(document).ready(function() {
var numbers = ['one', 'two', 'three'];
for (i in numbers) {
(function () {
var nr = numbers[i];
var li = $('<li>' + nr + '</li>');
li.click(function() {
var newVariable = String(nr);
alert(i); // 2
alert(nr); // three
alert(newVariable); // three
alert(li.html()); // three
});
$('ul').append(li);
}());
}
});
It's also bad practise for using for in
for iterating over an array. It should be strictly used for iterating over object fields. Use the for(;;;)
instead.
You need to attach any data on the elements or on http://api.jquery.com/jQuery.data/ in order to reuse later on.
e.g
...
var li = $('<li>' + nr + '</li>');
jQuery.data(li, "the-value", foo);
li.click(function() {
var foo = jQuery.data(li, "the-value");
...
}
This is working as it should, you are asking the click event to use these variables (not absolute values) and by the time the method is called the variables are at their 'max' values.
Try using the title attribute to store the value you want to return, i.e.:
var li = $('<li title="' + nr + '">' + nr + '</li>');
Then your alert would be:
alert(this.attr('title'));
Not tested but that should work or at least set you on the right track.
精彩评论