我有以下循环。目标是在用户选择下拉列表中的某些选项时自动显示文本框。
出于某种原因,在以下代码中,循环将“赞助商”字段分配给关联数组“blurb”。我无法弄清楚为什么。我怎样才能做到这一点?
非常感谢。
function add_fields_on_change ()
{
var map = {
"sponsor" : Array("New Sponsor", "new_sponsor"),
"blurb" : Array("New Blurb Suggestion", "new_blurb")
};
for (field in map)
{
alert($('.bound[name='+field+']').val()); //alerts as expected
$('.bound[name='+field+']').change(function() {
alert(map[field][0]); //alerts "New Blurb Suggestion" for both "sponsor" and "blurb" fields
if ($(this).val() == map[field][0])
{
$('.hidden[name='+map[field][1]+']').show();
}
});
}
}
答案 0 :(得分:4)
原因是你正在创建的事件处理程序(它是一个闭包)对field
变量有一个持久引用,而不是副本从创建函数时开始。因此,创建的所有事件处理程序将看到field
(分配给它的最后一个值)的相同值。
因为您已经在使用jQuery,所以最简单的解决方案可能就是使用$.each
:
function add_fields_on_change ()
{
var map = {
"sponsor" : Array("New Sponsor", "new_sponsor"),
"blurb" : Array("New Blurb Suggestion", "new_blurb")
};
$.each(map, function(field, value) {
alert($('.bound[name='+field+']').val()); //alerts as expected
$('.bound[name='+field+']').change(function() {
alert(map[field][0]); //alerts "New Blurb Suggestion" for both "sponsor" and "blurb" fields
if ($(this).val() == map[field][0])
{
$('.hidden[name='+map[field][2]+']').show();
}
});
});
}
这是有效的,因为事件处理程序关闭了对你传递给each
的迭代器函数的调用,因此它们每个都得到自己的field
参数,它永远不会改变。
如果你想在没有使用$.each
的情况下出于某种原因这样做,你会做这样的事情:
function add_fields_on_change ()
{
var map = {
"sponsor" : Array("New Sponsor", "new_sponsor"),
"blurb" : Array("New Blurb Suggestion", "new_blurb")
};
var field;
for (field in map)
{
alert($('.bound[name='+field+']').val()); //alerts as expected
$('.bound[name='+field+']').change(createHandler(field));
}
function createHandler(f) {
return function() {
alert(map[f][0]); //alerts "New Blurb Suggestion" for both "sponsor" and "blurb" fields
if ($(this).val() == map[f][0])
{
$('.hidden[name='+map[f][3]+']').show();
}
};
}
}
这是相同的原则,事件处理程序关闭对createHandler
的调用并使用f
参数,该参数对于每个调用是唯一的,并且我们从不为其分配新值。
请注意,我声明了field
变量。您的原始代码中缺少该声明,这意味着您正在成为Horror of Implicit Globals的牺牲品。
更多阅读:
答案 1 :(得分:0)
您可以通过向字段添加自定义属性来实现此目的,从而避免出现关闭问题:
function add_fields_on_change ()
{
var map = {
"sponsor" : Array("New Sponsor", "new_sponsor"),
"blurb" : Array("New Blurb Suggestion", "new_blurb")
};
for (field in map)
{
$('.bound[name='+field+']').attr('data-name', map[field][0]);
$('.bound[name='+field+']').attr('data-hidden', map[field][1]);
$('.bound[name='+field+']').change(function() {
if ($(this).val() == this.attr('data-name'))
{
$('.hidden[name='+this.attr('data-hidden')+']').show();
}
});
}
}