如何阻止Javascript的forEach?

我正在玩nodejs和mongoose – 试图find深入的评论嵌套recursionfunc和foreach内的具体评论。 有没有办法阻止nodejs forEach? 据我所知每一个迭代是一个函数,我不能只是做“rest”,只有“返回”,但这不会停止foreach。

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

你不能从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来中断。

打破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循环,但这是我的解决scheme:

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

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

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

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

如果您不介意使用第三方库,则可以使用Lodash的forEach函数。

例:

 var _ = require('lodash'); _.forEach(comments, function (comment) { do_something_with(comment); if (...) { return false; // Exits the loop. } }) 

Array.forEach不能被破坏,使用try...catch或hacky方法,如Array.everyArray.some只会让你的代码更难理解。 这个问题只有两个解决scheme:

1)使用旧的for循环:这将是最兼容的解决scheme,但是当在大块代码中经常使用时可能非常难以阅读:

 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年,只有less数浏览器和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成为新标准之前,大多数stream行的库(如AngularJS和jQuery)都提供了自己的循环方法,这些方法可以优于JavaScript中提供的任何方法。 对于那些还没有使用这些大型库的用户来说,他们正在寻找轻量级的select,这样的解决scheme可以被使用,并且几乎可以与ECMA6保持一致,同时保持与旧版浏览器的兼容性。

我想你想使用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循环,下面是示例示例

  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; 

forEach不会中断返回,有难看的解决scheme来得到这个工作,但我build议不要使用它,而是尝试使用Array.prototype.someArray.prototype.every

 var ar = [1,2,3,4,5]; ar.some(function(item,index){ if(item == 5){ return; } console.log("item is :"+item+" index is : "+index); }); 

如果覆盖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)\ }") 

不幸的是,使用这个解决scheme,你不能在你的callback中使用普通的中断,你必须在string中包装无效的代码,本地函数不能直接工作(但你可以解决这个问题)

快乐打破!

Wy不使用普通的返回?

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

它会从'recurs'函数返回。 我这样使用它。 虽然这不会从每个事件中突破,但是从整个function来看,在这个简单的例子中它可能会起作用

jQuery提供了一个each()方法,而不是forEach() 。 你可以通过返回false来突破eachforEach()是ECMA-262标准的一部分,突破我意识到的唯一方法是抛出一个exception。

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

丑,但是做这个工作。