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. 不过,我可以想出三种方法来伪造它。

1.丑陋的方式:传递第二个参数以forEach用作上下文,并在其中存储一个布尔值,然后使用一个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 回答
42

forEach 在返回时不会中断,有一些丑陋的解决方案可以完成这项工作,但我建议不要使用它,而是尝试使用Array.prototype.someArray.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);
});

于 2017-04-20T16:35:03.643 回答
39

在某些情况下Array.some可能会满足要求。

于 2012-10-04T10:03:10.350 回答
31

正如其他人指出的那样,您无法取消forEach循环,但这是我的解决方案:

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

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

当然这实际上并没有打破循环,它只是阻止在“break”之后的所有元素上执行代码

于 2011-06-07T05:26:00.513 回答
23

我猜你想使用 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 }
于 2017-07-11T07:02:36.310 回答
10

forEach如果您不介意使用 3rd 方库,可以使用 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或 hacky 方法,例如Array.everyorArray.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 成为新标准之前,大多数流行的库(例如 AngularJS 和 jQuery)都提供了自己的循环方法,这些方法可以优于 JavaScript 中可用的任何方法。同样对于那些还没有使用这些大型库并且正在寻找轻量级选项的人来说,可以使用这样的解决方案,并且几乎可以与 ECMA6 相提并论,同时保持与旧浏览器的兼容性。

于 2016-06-18T02:34:38.273 回答
1

一旦满足条件,下面的代码将打破 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;
于 2017-06-13T04:01:01.243 回答
-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 回答