470

私は Node.js と Mongoose で遊んでいます — 再帰関数と内部でネストされた深いコメントで特定のコメントを見つけようとしていforEachます。Node.js を停止する方法はありforEachますか? 私が理解しているように、すべてforEachの反復は関数であり、単に行うことはできませんbreakreturn、これは停止しませんforEach

function recurs(comment) {
    comment.comments.forEach(function(elem) {

        recurs(elem);

        //if(...) break;

    });
}
4

13 に答える 13

1181

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

1. 醜い方法: context として使用forEachする 2 番目の引数を渡し、そこにブール値を格納してから、. これはひどく見えます。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
})

壊しsome()たい場合は、代わりに使用できます。return true

于 2011-06-07T05:18:04.600 に答える
68

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;
        }
    }
}
于 2011-06-07T05:12:49.727 に答える
39

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

于 2012-10-04T10:03:10.350 に答える
31

他の人が指摘しているように、forEachループをキャンセルすることはできませんが、私の解決策は次のとおりです。

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

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

もちろん、これは実際にループを中断するわけではなく、「中断」に続くすべての要素でコードの実行を防ぐだけです。

于 2011-06-07T05:26:00.513 に答える
10

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

例:

var _ = require('lodash');

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

    if (...) {
        return false;     // Exits the loop.
    }
})
于 2016-10-21T12:17:38.997 に答える
7
    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; //<--!!!
        }
    });
于 2016-01-09T17:10:06.033 に答える
4

Array.forEachまたはtry...catchなどのハッキーな方法を使用すると、コードが理解しにくくなるだけです。この問題の解決策は 2 つだけです。Array.everyArray.some

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 で利用できるものよりも優れた独自のループ メソッドを提供します。また、これらの大きなライブラリをまだ使用しておらず、軽量のオプションを探している人のために、このようなソリューションを使用でき、古いブラウザーとの互換性を維持しながら ECMA6 とほぼ同等になります。

于 2016-06-18T02:34:38.273 に答える
-6

Array メソッドを上書きすると、forEach ループから抜けることができます。

(function(){
    window.broken = false;

        Array.prototype.forEach = function(cb, thisArg) {
            var newCb = new Function("with({_break: function(){window.broken = true;}}){("+cb.replace(/break/g, "_break()")+"(arguments[0], arguments[1], arguments[2]));}");
            this.some(function(item, index, array){
                 newCb(item, index, array);
                 return window.broken;
            }, thisArg);
            window.broken = false;
        }

}())

例:

[1,2,3].forEach("function(x){\
    if (x == 2) break;\
    console.log(x)\
}")

残念ながら、このソリューションでは、コールバック内で通常のブレークを使用できません。無効なコードを文字列でラップする必要があり、ネイティブ関数は直接動作しません (ただし、回避できます)。

ハッピーブレイク!

于 2016-05-16T22:23:54.013 に答える
-11

プレーンリターンを使用しないのはなぜですか?

function recurs(comment){
comment.comments.forEach(function(elem){
    recurs(elem);
    if(...) return;
});

「recurs」関数から戻ります。こんな感じで使っています。これは forEach からではなく関数全体から壊れますが、この単純な例ではうまくいくかもしれません

于 2014-03-12T18:17:20.753 に答える
-18

jQuery はeach()ではなくメソッドを提供しますforEach()eachを返すことで抜け出すことができますfalseforEach()は ECMA-262 標準の一部であり、私が認識している唯一の方法は、例外をスローすることです。

function recurs(comment) {
  try {
    comment.comments.forEach(function(elem) {
      recurs(elem);
      if (...) throw "done";
    });
  } catch (e) { if (e != "done") throw e; }
}

醜いですが、仕事をします。

于 2011-06-07T05:22:09.117 に答える