jQuery中的可变范围问题

Variable Scope Issue in jQuery

本文关键字:范围 问题 jQuery      更新时间:2023-09-26

我正试图在jQuery中捕获两个select元素的change()事件。我尝试在一个循环中完成它,这样我就不必剪切和粘贴相同的代码。

此线路通过var x = $("#"+fields[i]).val(); 出现问题

fields = ['foo', 'bar'];
for (var i=0; i < fields.length; i++)
{
    $("#"+fields[i]).change(function () {
            var x = $("#"+fields[i]).val();
            alert(x);
    });
}
<form>
    <select id="foo">
        <option value="first">first</option>
        <option value="second">second</option>
    </select>
    <select id="bar">
        <option value="third">third</option>
        <option value="fourth">fourth</option>
    </select>
</form>

http://jsfiddle.net/mLc5p/6/

编辑

对不起,这是一个过于简化的例子。事实上,我想得到附近的一堆田地,而不必做一堆剪切和粘贴。这是我的实际代码:

var fieldnames = ['start_date', 'end_date']
for (var i=0; i < fieldnames.length; i++)
{
    var fieldname = fieldnames[i];
$("#event_"+fieldname+"_date, #event_"+fieldname+"_hour, #event_"+fieldname+"_minute, #event_"+fieldname+"_ampm").change(function(){
    var d = $("#event_"+fieldname+"_date").val();
    var h = $("#event_"+fieldname+"_hour").val();
    var m = $("#event_"+fieldname+"_minute").val();
    var ampm = $("#event_"+fieldname+"_ampm").val();
    $("#event_"+fieldname).val(d + ' ' + h + ':' + m + ampm);
    if ( $("#event_"+fieldname).val() == " :" ){
        $("#event_"+fieldname).val("");
    }
    if (fieldname == "start_date")
    {
        $.validator.methods.validMoment.call(this, $("#event_"+fieldname).val(), $("#event_"+fieldname), null);
    }else
    {
        $.validator.methods.validOptionalMoment.call(this, $("#event_"+fieldname).val(), $("#event_"+fieldname), null);
    }
});

}

我想我可以用Ruby生成代码,而不必担心用Javascript做任何技巧,但我很好奇。。。

您应该将其更改为

$("#"+fields[i]).change(function () {
        var x = this.value;
        alert(x);
});

对于您的代码,问题是无论您更改什么字段,都将始终显示最后一个字段的值(由于for周期)。换句话说:当change事件发生时,alert语句中fields[i]的值始终显示

最后一个字段的值未定义(Chris正确地提醒我)。

附带说明一下,没有必要使用jQuery:您可以使用this.value

只需在迭代中使用$.each即可。

var fields = ['foo', 'bar'];
$.each(fields, function(idx, field){
     $("#"+field).change(function () {
            var x = $("#"+field).val();
            alert(x);
    });
});

http://jsfiddle.net/mLc5p/12/

这将解决范围问题。问题是i将在循环iteartion的法线之后为2,并且i不会保存在每次迭代的范围中。在处理程序的执行结束时,i将始终为2。$.each自动保持每个站点的范围分离。

为了完整起见,这个问题的非jQuery解决方案是:

var fields = ['foo', 'bar'];
for (var i=0; i < fields.length; i++){
    (function(i){
       $("#"+fields[i]).change(function () {
            var x = $("#"+fields[i]).val();
            alert(x);
        });
    })(i);
}

其具有与上述解决方案基本相同的效果。你的代码被包装在一个函数中,我被"粘"在你的函数范围上,作为自执行函数的参数。

没有。。。无循环。只需创建一个事件处理程序并使用this关键字即可获得正确的元素。

$("select").change(function(){
    var x = $(this).val();
    alert(x);
});

下面是一个工作示例

您应该像一样tru this

var fields = ['foo', 'bar'];
for (var i=0; i < fields.length; i++)
{
    $("#"+fields[i]).change(function () {
        var x = $(this).val();// use this in place of fields[i]
        alert(x);
    });
}

工作Fiddle

您需要在for循环中使用此指针。Fiddle

var fields = ['foo', 'bar'];
for (var i=0; i < fields.length; i++)
{
    $("#"+fields[i]).change(function () {
            var x = $(this).val();
            alert(x);
    });
}

尝试以下操作:

fields = ['foo', 'bar'];
for (var i=0; i < fields.length; i++)
{
    $("#"+fields[i]).change(function () {
        var x = $(this).val();
        alert(x);
    });
}

工作小提琴:http://jsfiddle.net/mLc5p/10/

替换:

var x = $("#"+fields[i]).val();  

收件人:

var x = $(this).val();