如何停止 Javascript forEach?

IT技术 javascript ecmascript-5
2021-01-22 02:47:48

我正在使用 Node.js 和 Mongoose - 试图在递归函数嵌套的深层注释中找到特定的注释forEach有没有办法阻止 Node.js forEach据我所知,每次forEach迭代都是一个函数,我不能只做breakreturn但这不会停止forEach

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

        recurs(elem);

        //if(...) break;

    });
}
6个回答

你不能从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打破你可以改用

不幸的是,使用 every() 或 some() 不能解决您想要中断特定值并返回它的情况。ECMAScript2015 new for...of ( developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... ) 可以帮助解决这部分问题,但缺点是该解决方案可能会导致旧浏览器出现更多问题。如果您愿意完全改变路线并使用不同的更通用的方法,这样的解决方案 ( github.com/nbouvrette/forEach ) 可以帮助您并可能解决其他问题。
2021-03-14 02:47:48
应该有数字 4。 美丽的方式:使用 some()
2021-03-17 02:47:48
或者更优雅地,放在return !you_want_to_break循环内而不是 if..else 块。保存两行。:-)
2021-03-20 02:47:48
every 支持除 IE7 和 8 之外的所有地方(我必须查找它,所以我想我会分享)
2021-03-21 02:47:48
+1,虽然对我来说使用some()return true当你想打破时听起来更自然
2021-04-06 02:47:48

突破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;
        }
    }
}
正如接受的答案所述,可以通过将 forEach 函数放入内部来实现。
2021-03-17 02:47:48
肯定是,但是使用异常来控制程序流是一个不好的坏习惯
2021-03-30 02:47:48

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

@imalhasarangaperera 在这里您可以找到当前的浏览器支持。developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
2021-03-14 02:47:48
浏览器支持如何?
2021-03-15 02:47:48
这应该是规范的答案,因为一旦找到正确的元素,它实际上会停止处理。虽然forEachevery(据我所知)可以被破解以在它找到的第一个元素上返回 true,但它仍然会贯穿整个数组。其次,Javascript 不执行尾部优化,因此在 ES6 出现之前,所有递归函数本质上都是脆弱的。
2021-03-28 02:47:48

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);
});

抱歉有错误,您需要返回 true
2021-03-21 02:47:48
它有效,但它会迭代数组的所有成员
2021-03-25 02:47:48

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

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

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

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

@PedroFerreira 我的论点是有效的。我没有冒犯任何人。我们需要批评我们的代码以使其更好。我宁愿阅读其他实现并帮助他们改进它而不是重新发明轮子。
2021-03-16 02:47:48
我认为这个解决方案不是一个好主意。假设您正在循环 10000 个元素并且您的条件在第二个元素处停止,那么您将无所事事地进行 9998 次不必要的迭代。最好的方法是使用someevery
2021-03-28 02:47:48
巧妙使用命名函数表达式
2021-03-31 02:47:48
我喜欢这个。我只是将最后一行结合起来loop.stop = condition它不应该有任何区别,因为当它设置为true它不会再运行。
2021-04-02 02:47:48
@Ali zyklus 说......这是另一个有效的解决方案!取决于你的情况......为什么人们花时间批评而不是提出新的不同解决方案......?!?!?
2021-04-02 02:47:48