2013-08-02 42 views
2

我試圖在jQuery中爲兩個select元素捕獲change()事件。我試圖在循環中完成,所以我不必剪切和粘貼相同的代碼。雖然var x = $("#"+fields[i]).val();jQuery中的變量作用域問題

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/

EDIT

這條線具有問題

對不起,那是一個過於簡化的例子。我實際上想得到一堆附近的領域,而不必做一堆剪切和粘貼。這裏是我的實際代碼:

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); 
    } 
}); 

}

我想我可能只是產生,而不必擔心在Javascript中做任何技巧在Ruby中的代碼,但我很好奇...

+0

使用:'var x = this.value;'http://jsfiddle.net/mLc5p/8/ – Joe

回答

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); 
} 

具有basicly作爲上述溶液中相同的效果。你的代碼被封裝在一個函數中,我被「粘」到你的函數作用域,作爲自執行函數的一個參數。

+0

我認爲這是我想要的。因爲我的例子太簡單了,所以我用實際的代碼更新了我的例子。 – Dex

1

Nooooo ...沒有循環。只需創建一個事件處理程序並使用this關鍵字來獲取正確的元素。

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

Here is a working example

+0

這是一個過分簡化的例子。實際上,我有很多值要讀取附近的值。它看起來像很多切割和粘貼 – Dex

+0

@Dex:所以展示真實的例子,我相信會有更好的方式 – musefan

+0

更新我的例子 – Dex

2

你應該把它變成

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

與您的代碼,問題是你改變哪個領域,你將始終顯示最後一個字段的值(由於for週期)。換句話說:當發生change事件時,alert語句中fields[i]的值總是顯示最後一個字段的值未定義(正如Chris正確提醒我的那樣)。

的旁註有沒有必要使用jQuery:你可以使用this.value

+0

它甚至不是最後一個元素。由於for循環中的'i ++'和字段[2]是未定義的,因此在迭代之後由於'i'爲2而未定義。 – Chris

+0

是的,在上次迭代之後,'i'確實是2。 – fcalderan

0

你應該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); 
    }); 
} 

Working Fiddle

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); 
    }); 
} 
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/

0

替換:

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

要:

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