短路 Array.forEach 就像调用 break

IT技术 javascript arrays foreach
2021-02-05 19:24:27
[1,2,3].forEach(function(el) {
    if(el === 1) break;
});

如何使用forEachJavaScript 中的新方法执行此操作我试过了return;return false;而且breakbreak崩溃,return除了继续迭代什么都不做。

6个回答

有没有内置的能力breakforEach要中断执行,您必须抛出某种异常。例如。

var BreakException = {};

try {
  [1, 2, 3].forEach(function(el) {
    console.log(el);
    if (el === 2) throw BreakException;
  });
} catch (e) {
  if (e !== BreakException) throw e;
}

JavaScript 异常并不是非常漂亮。for如果你真的需要在break里面,传统的循环可能更合适

Array#some

相反,使用Array#some

[1, 2, 3].some(function(el) {
  console.log(el);
  return el === 2;
});

这是有效的,因为只要以数组顺序执行的任何回调some返回true,就会返回true,从而使其余的执行短路。

some,它的反面every(将在 a 处停止return false),并且forEach都是 ECMAScript Fifth Edition 方法,需要将它们添加到Array.prototype缺少它们的浏览器中。

我认为“一些”在这里很好,为什么不使用早期退出优化-
2021-03-09 19:24:27
异常处理不应用作控制流。时期。
2021-03-11 19:24:27
使用起来Array#some真的很不错。首先它兼容大多数浏览器,包括 ie9 和 firefox 1.5 也能很好地工作。我的示例用例是在一个 range[a,b] 数组中查找索引,其中一个数字在下边界和上边界对之间,测试并在找到时返回 true。for..of尽管仅适用于较新的浏览器,但将是下一个最佳解决方案。
2021-03-26 19:24:27
@frank 我写了一个只有一个循环结构的 esolang:forever . 所有其他循环构造均由forever适当的可迭代异常构成,例如ContinueIterationand StopIteration(这break是一个要引发的宏)。一方面:从不。另一方面:总是。在抓手上:有时您评论中的“PERIOD”暗示可能有引文来支持您的建议?
2021-03-26 19:24:27
感谢自扫门前雪someevery,这应该是在顶部的答案。无法理解为什么人们认为它的可读性较差。太棒了!
2021-04-06 19:24:27

现在在 ECMAScript2015(又名 ES6)中使用新的for of loop有更好的方法来做到这一点例如,此代码不会打印数字 5 之后的数组元素:

let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
for (let el of arr) {
  console.log(el);
  if (el === 5) {
    break;
  }
}

从文档:

无论对于...在对...的语句迭代的东西。它们之间的主要区别在于它们迭代的内容。为...在声明中遍历对象的枚举的属性,在原来的插入顺序。对...的语句迭代数据迭代的对象定义要遍历。

需要迭代中的索引吗?您可以使用Array.entries()

for (const [index, el] of arr.entries()) {
  if ( index === 5 ) break;
}
不是建议不要将 for...in 与数组一起使用吗?
2021-03-12 19:24:27
这是“for of”,这是一个非常干净的解决方案……但这也是一个 ES6 特性,所以请注意,这仅在您的环境设置为 ES6 时才有效。
2021-03-13 19:24:27
@emostafa 您对不推荐用于数组的for in循环是正确的,但这种方法实际上使用了 for of循环。
2021-03-24 19:24:27
我发现自己经常使用这个解决方案,我也将它用于对象。对于对象,您可以Object.entries(myObject)像使用for..in数组一样使用它,然后使用它请注意,JS 数组基本上是引擎盖下的对象:blog.niftysnippets.org/2011/01/myth-of-arrays.html
2021-03-31 19:24:27
@superhero 您可以在 for...of 循环中获取元素的索引,您只需要使用entries. for (const [index, element] of someArray.entries()) { // ... }
2021-04-08 19:24:27

您可以使用每种方法:

[1,2,3].every(function(el) {
    return !(el === 1);
});

ES6

[1,2,3].every( el => el !== 1 )

对于旧浏览器支持使用:

if (!Array.prototype.every)
{
  Array.prototype.every = function(fun /*, thisp*/)
  {
    var len = this.length;
    if (typeof fun != "function")
      throw new TypeError();

    var thisp = arguments[1];
    for (var i = 0; i < len; i++)
    {
      if (i in this &&
          !fun.call(thisp, this[i], i, this))
        return false;
    }

    return true;
  };
}

更多细节在这里

@Valdemar,但是能every 保证按顺序进行调用吗?
2021-03-13 19:24:27
现在在 ES6 中干净整洁 - [1,2,3].every( el => el !== 1 )
2021-03-14 19:24:27
改变代码的意图。很坏。
2021-03-15 19:24:27
@Pacerier,你可以在ES6规范中看到索引k从0开始递增1的算法:http : //www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.every
2021-03-17 19:24:27
@Pacerier,是的,大多数流行的实现都可以正常工作。如果您关心嵌入式实现,通常是 Opera 或 webkit。方法 every 为数组中存在的每个元素调用 callbackfn 一次,按升序,直到找到一个 callbackfn 返回 false 的元素也看第 7 步。让 k 为 0。8.e 将 k 增加 1。
2021-03-21 19:24:27

引自MDN 文档Array.prototype.forEach()

没有办法阻止或打破一个forEach()比抛出异常等循环。如果您需要这种行为,则该.forEach()方法是错误的工具,请改用普通循环。如果您正在测试谓词的数组元素并需要布尔返回值,则可以使用every()some()代替。

对于您的代码(在问题中),如@bobince 所建议的,请Array.prototype.some()改用。它非常适合您的用例。

Array.prototype.some()为数组中存在的每个元素执行一次回调函数,直到找到一个回调函数返回真值(转换为 a 时变为真值的值Boolean)。如果找到这样的元素,则some()立即返回 true。否则,some()返回假。仅对已分配值的数组索引调用回调;不会为已删除或从未分配值的索引调用它。

声纳标记它,不使用从 array.some() 返回的值。逻辑是仅将其用于循环。
2021-03-16 19:24:27
这是正确答案。'some' 的作用与 foreach/break 的作用完全相同。它循环直到迭代 n = true。
2021-03-23 19:24:27

不幸的是,在这种情况下,如果您不使用forEach. 而是使用常规for循环,它现在将完全按照您的预期工作。

var array = [1, 2, 3];
for (var i = 0; i < array.length; i++) {
  if (array[i] === 1){
    break;
  }
}
令我震惊的是,与该正确答案的更高性能、更少代码和更好可读性相比,最高投票可能是最糟糕的实现。抛出异常……真的吗?传统的 for 循环还不够 kewl 吗?
2021-03-24 19:24:27
@gdbj 我同意你的说法并使用了这种方法,但真正让我震惊的是没有这些技巧就无法退出 forEach,现在这是糟糕的设计。
2021-03-28 19:24:27
@gdbj 我也同意,但问题更多在于 Stack Overflow 及其指导方针。这个问题特别要求解决一个 Array.forEach 循环的解决方案。接受的答案就是……以一种非常丑陋的方式。从技术上讲,这个答案是不正确的,即使它以一种久经考验的真实方式实现了相同的目标。
2021-04-02 19:24:27