標籤:blog java 使用 os io for ar 問題
在js中,用迴圈來為一對元素隊列的元素繫結事件,是一個常見的問題。
通常進入誤區的新人,都會這麼寫代碼: (假設元素隊列為o,預設使用jQuery)
//error method
var o =$(‘.blockHead‘);for(var i=0; i<o.length; i++){o[i].onclick = function(){function(i){ alert(i);}}}
當然這種情況下,你會發現每個元素點擊運行時,顯示的 i值 都是 o.length-1;
因為js的函數是調用時觸發,綁定事件的時候i值並沒有被傳入執行函數裡。
作為非同步監聽的事件,點擊事件發生的時候,迴圈已經結束,此時的 i值 為[o.length-1], 觸發事件傳遞的參數自然是同一個最大值,而不是預期不同元素傳不同值。
解決辦法思路:將綁定事件程序中得到的i值,在執行函數域裡儲存起來;調用時自然就得到相應的結果。
方法一: 使用閉包函數儲存i值
var o = $(‘.blockHead‘);for(var i=0; i<o.length; i++){o[i].onclick = (function closure(ii){ //var ii; //we save ii in this scopereturn function(){alert(ii);}})(i);}
如上,colsure是一個閉包函數(closure函數名可省去,作匿名閉包函數),聲明後立即執行,傳遞了i值,於是在它的函數域裡儲存了i值(arguments參數列表裡);
函數的返回結果是事件處理函數,其參數ii就是colsure裡儲存的ii值,也就是迴圈時就傳遞的i值。
ps:方法一是非常常見的處理該問題的解決方案;在尋找解決方案的過程裡,我發現了另一個寫法,如下。
方法二: 將事件綁定的代碼寫在一個外圍函數裡
var o = $(‘.blockHead‘);for(var i=0; i<o.length; i++){attach(i,o[i]);function attach(ii,o){o.onclick = function(){alert(ii);};}}//或者 直接在聲明函數後立刻執行var o = $(‘.blockHead‘);for(var i=0; i<o.length; i++){(function attach(ii,o){o.onclick = function(){alert(ii);};})(i,o[i]);}
同樣的道理,在attach的函數域裡,onclick事件得到的ii值已經是執行迴圈便擷取的的i,而外部的i執行完迴圈後的結果是什麼已經跟內部沒有關係了。
稍許比方法一麻煩的是,參數需要多傳遞一個元素的引用。