2012-02-11 64 views
0

在我的應用程序,我需要做一些反覆與arraylike對象arraylike對象。幾個問題時,迭代器在JavaScript

所以我編寫自定義util的方法:

Util.forEach=function(iterator,callback,context){ 
    if(iterator.length){ 
    for(var i=0;i<iterator.length;i++){ 
     var val=iterator[i]; 
     callback && callback.call(context||null,val,i); 
    } 
    } 
} 

然後我滿足一些問題:

假設我有一個數組:var進制= [1,2,3,4,5];

1.如何打破循環?

例如,如果我想找到如果值「2」被包括在陣列中,我可以嘗試:

Util.forEach(ary,function(value,index){ 
    if(value==2){ 
    //find mached value,now I should break and return this value. 

    //but I can not use 'break' in this context. 
    } 
}); 

2.陣列的刪除值時迭代

如果我想刪除的陣列值「2」,我可以試試這個:

Util.forEach(ary,function(value,index){ 
    if(value==2){ 
    //delete it. 
    ary.splice(i,1); 
    // I wonder if this is the safe way? 
    } 
}); 

由於在Java中遍歷數組的時候,我們不能做到這一點,會導致併發異常。

雖然我運行上面的代碼沒有任何錯誤,但我不知道這是否是最好的做法是什麼?

回答

0

第一個問題可以通過檢查從回調的返回值和停止迭代如果返回false來解決。然後,您可以通過從回調中返回false來停止迭代。返回除false之外的任何內容(包括不返回任何內容)將繼續迭代。 jQuery使用這種返回值技術取消迭代器.each()中的迭代。並稱,到你的代碼,它應該是這樣的:

Util.forEach=function(iterator,callback,context){ 
    if (iterator.length && callback) { 
     for(var i = 0; i < iterator.length; i++){ 
      var val=iterator[i]; 
      if (callback.call(context||window,val,i) === false) { 
       break; 
      } 
     } 
    } 
} 

MDN documentation爲的forEach,你可以看到一個簡單的實現。

在第二個問題上,這種類型的實現不允許在迭代點之前或之前插入或刪除元素,因爲這會導致迭代中跳過某些元素或者某些對象迭代多次。明顯的解決方法是在迭代之前製作對象的副本,這在不需要時效率不高。 catchthrow -

+0

謝謝你的回覆。對於第二個問題,如你所說製作副本效率不高,還有其他選擇? – hguser 2012-02-12 00:47:10

+0

@hguser - 你不能吃你的蛋糕,也不能吃它。您要麼創建數組的副本,以便對原始數據的更改不會影響每個元素的迭代。或者,你依靠什麼類型的修改就可以,哪些類型不是。挑一個或另一個。例如,可以更改任何元素。甚至可以在當前元素之後添加或刪除任何元素。在當前元素之前或包括當前元素添加/刪除元素是不正確的。 – jfriend00 2012-02-12 01:01:37

+0

@hguser - 如果你想在當前元素之前添加/刪除,那麼寫一個'for'循環而不是'.each(fn)',你可以手動控制當你修改數組時,迭代索引發生了什麼。到你想爲特定情況發生的事情。 – jfriend00 2012-02-12 01:02:29

1

一般情況下,你可以通過使用tryforEach式的方法打破了。

var value = 'Not Found'; 
try { 
    Util.forEach(ary, function(value, index) { 
     if(value == 2) { 
      throw value; //<-- Throw the found result: Terminates current forEach 
     } 
    }); 
} catch (found) {  // Catch the thrown result 
    value = found; 
} 
0

如何打破循環?

你不應該打破從forEach。這就是爲什麼它被稱爲「爲每個」,而不是「爲某些」。 「易碎」JS迭代器是every()(當回調返回false時停止)和some()(當回調返回true時停止)。在你的代碼

尋找再次它讓我覺得你需要的是一個indexOf一種方法,而不是一個迭代器。當迭代

迭代不應該使底層陣列的任何變化的陣列的

移除值。您必須實施filter()並使用它來生成新陣列。

請參閱js iteration methods瞭解更多詳情。

+0

如果仔細觀察,您會發現OP沒有使用'Array.prototype.forEach',而是使用自定義的'Util.forEach'方法。 – 2012-02-11 17:54:11