web-dev-qa-db-ja.com

javascript forEachを停止する方法?

私はnodejsとmongooseで遊んでいます - 再帰的な関数とforeachでネストしている深いコメントの中で特定のコメントを見つけようとしています。 nodejs forEachを停止する方法はありますか?私はすべてのforEachの繰り返しが関数であることを理解していて、そして単に "break"をすることはできず、ただ "return"をすることができますが、これはforeachを止​​めません。

function recurs(comment){
    comment.comments.forEach(function(elem){
        recurs(elem);
        //if(...) break;
    });
}
310
kulebyashik

forEachから抜け出すことはできません。それを偽造するには3つの方法が考えられます。

1.醜い方法 forEachへの2番目の引数を context として使用し、そこにブール値を格納してからifを使用します。これはひどいね。

2.物議を醸す方法 :すべてをtry-catchブロックで囲み、中断したい場合は例外をスローします。これはかなり悪く見えます、そして パフォーマンスに影響を与えるかもしれません 、しかしカプセル化することができます。

3.楽しい方法 every()を使ってください。

['a', 'b', 'c'].every(function(element, index) {
  // Do your thing, then:
  if (you_want_to_break) return false
  else return true
})

return trueを壊したいのであれば、代わりにsome()を使うことができます。

786
slezica

Array#forEach から抜け出すことはできません。 (これを確認するために、リンクされたページでFirefoxでそれを実装するソースコードを調べることができます。)

代わりに、通常のforループを使用してください。

function recurs(comment) {
    for (var i = 0; i < comment.comments.length; ++i) {
        var subComment = comment.comments[i];
        recurs(subComment);
        if (...) {
            break;
        }
    }
}

(または、もう少し賢くなりたい場合、comment.comments[i]が常に目的語である場合は、:)

function recurs(comment) {
    for (var i = 0, subComment; subComment = comment.comments[i]; ++i) {
        recurs(subComment);
        if (...) {
            break;
        }
    }
}
40
Domenic

場合によっては Array.some がおそらくその要件を満たすでしょう。

31
igor

他の人が指摘したように、あなたはforEachループをキャンセルすることはできませんが、これが私の解決策です:

ary.forEach(function loop(){
    if(loop.stop){ return; }

    if(condition){ loop.stop = true; }
});

もちろん、これは実際にはループを壊しません、それはただ「break」に続くすべての要素でのコード実行を妨げるだけです

29
Mark Kahn

Array.prototype. findを使用したいと思います Findは配列内の特定の値を見つけると自動的に壊れます。

var inventory = [
  {name: 'apples', quantity: 2},
  {name: 'bananas', quantity: 0},
  {name: 'cherries', quantity: 5}
];

function findCherries(fruit) { 
  return fruit.name === 'cherries';
}

console.log(inventory.find(findCherries)); 
// { name: 'cherries', quantity: 5 }

forEachは復帰しても壊れません、この作品を手に入れるための醜い解決策がありますが、私はそれを使わないことをお勧めします。代わりにArray.prototype.someまたはArray.prototype.everyを使うようにしてください

var ar = [1,2,3,4,5];

ar.some(function(item,index){
  if(item == 3){
     return true;
  }
  console.log("item is :"+item+" index is : "+index);
});

サードパーティのライブラリを使用しても構わない場合は、Lodashの forEach 関数を使用できます。

例:

var _ = require('lodash');

_.forEach(comments, function (comment) {
    do_something_with(comment);

    if (...) {
        return false;     // Exits the loop.
    }
})
5
exmaxx

Array.forEachは壊れてはいけません、そしてtry...catchArray.everyArray.someのようなハックなメソッドを使うことはあなたのコードを理解することを難しくするだけです。この問題の解決策は2つしかありません。

1)古いforループを使用します。これは最も互換性のある解決策になりますが、大きなコードブロックで頻繁に使用される場合は非常に読みにくくなります。

var testArray = ['a', 'b', 'c'];
for (var key = 0; key < testArray.length; key++) {
    var value = testArray[key];
    console.log(key); // This is the key;
    console.log(value); // This is the value;
}

2)互換性が問題にならない場合は、新しいECMA6(2015仕様)を使用してください。 2016年になっても、この新しい仕様を適切にサポートしているブラウザとIDEはごくわずかです。これは反復可能なオブジェクト(例えば配列)に対しては有効ですが、反復不可能なオブジェクトに対してこれを使用したい場合は、Object.entriesメソッドを使用する必要があります。この方法は2016年6月18日現在ではほとんど利用できず、Chromeでもそれを有効にするための特別なフラグが必要です:chrome://flags/#enable-javascript-harmony。配列の場合、これらすべてを必要とするわけではありませんが、互換性は問題のままです。

var testArray = ['a', 'b', 'c'];
for (let [key, value] of testArray.entries()) {
    console.log(key); // This is the key;
    console.log(value); // This is the value;
}

3)多くの人が最初の選択肢も2番目の選択肢も良い候補ではないことに同意するでしょう。オプション2が新しい標準になるまで、AngularJSやjQueryなどの最も人気のあるライブラリは、JavaScriptで利用できるものよりも優れた独自のループメソッドを提供します。これらの大きなライブラリをまだ使っておらず、軽量のオプションを探している人のためにも、 this のような解決策を使うことができます。

3
    var f = "how to stop Javascript forEach?".split(' ');
    f.forEach(function (a,b){
        console.info(b+1);
        if (a == 'stop') {
            console.warn("\tposition: \'stop\'["+(b+1)+"] \r\n\tall length: " + (f.length)); 
            f.length = 0; //<--!!!
        }
    });
3

以下のコードは条件が満たされるとforeachループを中断します、以下はサンプル例です

    var array = [1,2,3,4,5];
    var newArray = array.slice(0,array.length);
    array.forEach(function(item,index){
        //your breaking condition goes here example checking for value 2
        if(item == 2){
            array.length = array.indexOf(item);
        }

    })
    array = newArray;
1
D G ANNOJIRAO