如何停止Javascript forEach?

我正在使用Node.js和Mongoose -试图在深层注释嵌套中找到特定的注释,其中包含递归函数和forEach。有没有办法停止Node.js forEach?正如我所理解的,每个forEach迭代都是一个函数,我不能只做break,只能做return,但这不会停止forEach

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


recurs(elem);


//if(...) break;


});
}
776993 次浏览

打破数组# 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。不过我能想到三种伪装方法。

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中断的话。

jQuery提供了each()方法,而不是forEach()方法。你可以通过返回false来打破eachforEach()是ECMA-262标准的一部分,据我所知,打破它的唯一方法是抛出异常。

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

很丑,但很管用。

正如其他人指出的那样,你不能取消forEach循环,但这里是我的解决方案:

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


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

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

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

我们不用普通的回报吗?

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

它将从'recurs'函数返回。我这样使用它。虽然这不会从forEach中中断,而是从整个函数中中断,但在这个简单的示例中,它可能是有效的

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

如果你重写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)\
}")

不幸的是,在这个解决方案中,你不能在回调中使用普通的break,你必须将无效代码包装在字符串中,本机函数不能直接工作(但你可以解决这个问题)

破坏快乐!

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

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相同,同时保持与旧浏览器的兼容性。

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

例子:

var _ = require('lodash');


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


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

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

下面的代码将在条件满足时中断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;

我猜你想用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 }