以下是我要完成的事情:在下面的mappings2
对象中,键是某些分组单选按钮的名称属性,值是一个列表,第一个字符串是一个附加到a的类该组的无线电(可能不止一个),让我们称这个单选按钮为特殊无线电,第二个字符串是一个类,当点击特殊无线电时必须启用其元素,下面的代码应该在更改之间切换一组无线电中的事件,在点击特殊无线电时执行一些代码,在点击该组中的其他非特殊无线电时执行不同的代码。
var mappings2 = {
// Group's name special-radio's class other radios
'DependientesEconomicos': ['hijos-dependientes', 'cuantos-hijos'],
'Preparatoria': ['otra-prepa', 'nombre-prepa'],
'ReproboAlgunaMateria': ['reprobo', 'causas-reprobo']
//'CausasReprobo': ['otra-causa-reprobo', 'otra-causa-reprobo-text']
};
(function (maps) {
for (grupo in maps) {
$('input[name="' + grupo + '"]').change(function (e) {
if ($(this).attr('class') === maps[grupo][0]) {
console.log(grupo + ' ' + $(this).attr('class') + ' true');
$('.' + maps[grupo][1]).attr('disabled', false);
} else {
$('.' + maps[grupo][1]).attr('disabled', true);
console.log(grupo + ' ' + $(this).attr('class'));
$('.' + maps[grupo][1]).val('');
}
});
}
})(mappings2);
代码适用于mappings2
的一个条目,但是当您添加更多内容时,只有最后一个条目有效,如果您单击以前组中的一个无线电,则日志显示正确的类,但{{1} }不是它所属的组,它显示了最后一个条目的组,所以这是所有错误的来源,我的问题是为什么。
jquery 1.5.1
感谢。
答案 0 :(得分:3)
问题是由闭包的工作方式引起的。
您的所有“更改”函数都引用相同的grupo
变量,因此无论其最终值是什么,都将是所有回调引用的值。
这是与此处描述的相同的问题/问题(并且具有相同的解决方案):
JavaScript closure inside loops – simple practical example
以下是显示相同问题的简化示例:
http://jsfiddle.net/Sly_cardinal/PM2Gf/6/
HTML:
<div class="wrong" style="border: 1px solid red">
<p>Incorrect: Clicking any item will show the last value of 'i'. i.e. class='11'</p>
<div class="1">a</div>
<div class="2">b</div>
<div class="3">c</div>
<div class="4">d</div>
<div class="5">e</div>
<!-- snip 5 other elements. -->
<p class="result"></p>
</div>
使用Javascript:
// Setup click handlers for the 'incorrect' divs.
for (var i = 1; i <= 10; i++){
$(".wrong ."+i).click(function(){
var t = $(this).text();
// This doesn't work because all of the handlers reference the same 'i' variable.
// When the loop finishes 'i == 11' so when you click on any of the divs they output the current value of 'i' which is eleven.
$(".wrong .result").text("You clicked div: class='"+i+"' content='"+t+"'");
});
}
当你点击其中一个div时,我们希望它打印出它在列表中的位置。因此,如果您点击“e”,我们希望它说我们点击了class='5'
元素。
但这不会发生 - 您点击的每一项都错误地表明它是class='11'
。
发生这种情况的原因是因为所有的变更函数都引用了相同的i
变量(就像你的'grupo'变量一样)。因此,当循环最终完成时i
的值为11.因此,所有div都打印出i
的值,即11。
这显示了如何更改创建事件处理程序以修复错误的方式:
http://jsfiddle.net/Sly_cardinal/mr6ju/2/
更新了javascript:
// Setup click handlers for the 'correct' divs.
for (var i = 1; i <= 10; i++){
// 1. Create an anonymous self-invoking function that
// returns a function.
var callback = (function(){
// 2. Copy the current value of 'i' to a new variable so
// that changes to 'i' cannot affect us.
var currentI = i;
// 3. Return the function definition that
// will be bound to the event listener.
return function(e){
var t = $(this).text();
// 4. NOTE that we reference 'currentI' and not 'i' here.
$(".result").text("You clicked div: class='"+currentI+"' content='"+t+"'");
};
}());
$("."+i).click(callback);
}
要解决这个问题,我们必须创建一个额外的内部函数,用于设置一个当前值为i
的新闭包。此内部函数将i
的值复制到名为currentI
的新变量,并返回引用currentI
而不是i
的新函数。
通过将值复制到新变量(仅存在于内部函数中),我们可以防止对i
的更改影响任何其他变量。
从这些示例中,您应该能够调整代码以创建一个新的嵌套函数,该函数将grupo
的值复制到一个新变量,并返回一个您指定为事件监听器的新函数。