jQuery中的变量范围问题

时间:2013-08-02 11:12:03

标签: javascript jquery

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

这一行虽然有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中做任何技巧,但我很好奇......

7 个答案:

答案 0 :(得分:2)

你应该把它改成

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

使用您的代码,问题在于您更改的任何字段都将始终显示最后一个字段的值(由于for周期)。换句话说:当change事件发生时,fields[i]语句中的alert值始终显示最后一个字段的值未定义(正如Chris正确提醒)我)。

作为旁注,不需要使用jQuery:您可以使用this.value

答案 1 :(得分:1)

Nooooo ......没有循环。只需创建一个事件处理程序并使用this关键字来获取正确的元素。

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

Here is a working example

答案 2 :(得分:1)

只需使用$.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在正常for循环迭代后将为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);
}

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

答案 3 :(得分:0)

你应该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);
    });
}

Working Fiddle

答案 4 :(得分:0)

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

var fields = ['foo', 'bar'];

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

答案 5 :(得分:0)

尝试以下:

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/

答案 6 :(得分:0)

替换:

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

致:

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