我正在使用nodejs和mongoose - 试图在深层注释中找到特定注释,并使用递归函数和foreach进行嵌套。有没有办法阻止nodejs forEach?据我所知,每个forEach迭代都是一个函数而且我不能只是“休息”,只能“返回”,但这不会阻止foreach。
function recurs(comment){
comment.comments.forEach(function(elem){
recurs(elem);
//if(...) break;
});
}
答案 0 :(得分:790)
你不能从forEach
中断。不过,我可以想出三种方法来伪造它。
<强> 1。丑陋的方式:将第二个参数传递给forEach
到use as context,并在那里存储一个布尔值,然后使用if
。这看起来很糟糕。
<强> 2。有争议的方式:在try-catch
块中包围整个事物,并在您想要中断时抛出异常。这看起来很糟糕may affect performance,但可以封装。
第3。有趣的方式:使用 every()
。
['a', 'b', 'c'].every(function(element, index) {
// Do your thing, then:
if (you_want_to_break) return false
else return true
})
如果您想要return true
打破,可以使用 some()
。
答案 1 :(得分:40)
无法突破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;
}
}
}
答案 2 :(得分:31)
在某些情况下,Array.some
可能会满足要求。
答案 3 :(得分:29)
正如其他人所指出的,你无法取消forEach
循环,但这是我的解决方案:
ary.forEach(function loop(){
if(loop.stop){ return; }
if(condition){ loop.stop = true; }
});
当然这实际上并没有打破循环,它只是阻止了“break”之后所有元素的代码执行
答案 4 :(得分:10)
我想你想使用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 }
答案 5 :(得分:6)
forEach在返回时没有中断,有一些难看的解决方案可以让这个工作,但我建议不要使用它,而是尝试使用Array.prototype.some
或Array.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);
});
&#13;
答案 6 :(得分:5)
如果您不介意使用第三方库,可以使用Lodash的forEach
功能。
示例:
var _ = require('lodash');
_.forEach(comments, function (comment) {
do_something_with(comment);
if (...) {
return false; // Exits the loop.
}
})
答案 7 :(得分:3)
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; //<--!!!
}
});
答案 8 :(得分:3)
Array.forEach
无法破解,使用try...catch
或hacky方法(例如Array.every
或Array.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为此新规范提供了良好的支持。虽然这适用于可迭代对象(例如Arrays),但如果要在非可迭代对象上使用它,则需要使用Object.entries
方法。自2016年6月18日起,此方法几乎无法使用,甚至Chrome也需要一个特殊标记来启用它:chrome://flags/#enable-javascript-harmony
。对于Arrays,您不需要所有这些,但兼容性仍然是一个问题:
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中的任何可用方法。此外,对于尚未使用这些大型库并且正在寻找轻量级选项的用户,可以使用this等解决方案,几乎与ECMA6相同,同时保持与旧浏览器的兼容性。
答案 9 :(得分: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;
答案 10 :(得分:-3)
如果覆盖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,你必须在字符串中包含无效的代码,并且本机函数不能直接工作(但你可以解决这个问题)
快乐打破!
答案 11 :(得分:-10)
Wy不使用普通回报?
function recurs(comment){
comment.comments.forEach(function(elem){
recurs(elem);
if(...) return;
});
它将从'recurs'函数返回。我这样用它。虽然这不会从forEach中脱离,而是从整个函数中解脱出来,在这个简单的例子中它可能起作用
答案 12 :(得分:-18)
jQuery提供each()
方法,而不是forEach()
。您可以通过返回each
来突破false
。 forEach()
是ECMA-262标准的一部分,打破我所知道的唯一方法是抛出异常。
function recurs(comment) {
try {
comment.comments.forEach(function(elem) {
recurs(elem);
if (...) throw "done";
});
} catch (e) { if (e != "done") throw e; }
}
丑陋,但是做到了。