我有这样的情况: 有 8 div-blocks,其中id为'rateN_wrapper',其中'N'是div的数量:
<div id="rate1_wrapper">
<a href="#" id="0_1">...</a>
<a href="#" id="0_2">...</a>
<a href="#" id="0_3">...</a>
</div>
<div id="rate2_wrapper">
<a href="#" id="1_1">...</a>
<a href="#" id="1_2">...</a>
<a href="#" id="1_3">...</a>
</div>
...
var ratings = new Array();
for (i=0; i < 8; i++)
{
ratings[i] = -1; // Default is unrated
}
for (i=0; i < 8; i++)
{
$('#rate' + i + '_wrapper a').click(function() {
ratings[i] = parseInt( $(this).attr('id').split('_')[1] );
console.debug(ratings);
});
}
我的工作是用点击链接的id(解析)填充需要的数组。但它总是只改变数组的最新元素(8)。为什么呢?
答案 0 :(得分:2)
这是由for循环中的闭包引起的问题。您可以通过解析父ID来查找id:
for (i=0; i < 8; i++)
{
$('#rate' + i + '_wrapper a').click(function() {
var parentId = $(this).parent('div').attr('id');
var index = /\d/.exec(parentId);
ratings[index] = parseInt( $(this).attr('id').split('_')[1] );
});
}
答案 1 :(得分:1)
因为您创建的函数正在关闭i变量。它在当前值时看到对i的引用,而不是创建函数时的值。 for循环退出后,我将为8,因此所有匿名函数都将更新ratings[8]
。我认为这可能会解决它:
for (i=0; i < 8; i++)
{
var idx = i;
$('#rate' + idx + '_wrapper a').click(function() {
ratings[idx] = parseInt( $(this).attr('id').split('_')[1] );
console.debug(ratings);
});
}
我不确定在循环体内声明var是否会在每次迭代时重新绑定它。如果是这样,那么匿名函数只会看到idx
在创建函数时的值。这是我知道的一种方式:
function CreateHandler(idx) {
return function() {
ratings[idx] = parseInt( $(this).attr('id').split('_')[1] );
console.debug(ratings);
}
}
for (i=0; i < 8; i++) {
$('#rate' + idx + '_wrapper a').click(CreateHandler(i));
}
因此,您创建了一个函数,该函数将使用正确的索引创建匿名函数。返回的匿名函数将在创建时看到idx
的值。