ChatGPT解决这个技术问题 Extra ChatGPT

如何打破 underscore.js 中的 _.each 函数

我正在寻找一种方法来停止 underscore.js _.each() 方法的迭代,但找不到解决方案。如果您执行 return false,jQuery .each() 可能会中断。

有没有办法停止下划线each()?

_([1,2,3]).each(function(v){
    if (v==2) return /*what?*/;
})
我认为不可能,因为原生 forEach 函数也不提供此功能。
通常在使用带有闭包的 each 时(在大多数语言中),您希望首先过滤您的列表。这样你就不用担心脱离它了。一般来说,如果您需要从迭代中提前中断,您可能会采用不同的方式来完成它。
Here are a couple 与 Groovy 相关的问题,其中行为(无法方便地从 each 闭包中断)类似于 JavaScript。
@Dmitry_F,正如其他人所指出的,你不能完全按照你的要求去做。但正如我所演示的,您可以使用 Array.every 来模拟您想要的行为。
@抢。干杯。第一条评论真的很有帮助。事实上,我本来可以用另一种方式来做这件事。

W
William

您不能中断 each 方法 - 它模拟原生 forEach 方法的行为,原生 forEach 不提供转义循环(除了引发异常)。

但是,所有的希望都不会消失!您可以使用 Array.every 方法。 :)

从那个链接:

every 对数组中存在的每个元素执行一次提供的回调函数,直到找到一个回调函数返回 false 值。如果找到这样的元素,every 方法会立即返回 false。

换句话说,您可以像这样 (link to JSFiddle) 做一些复杂的事情:

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

这将通过 3 提醒 1,然后“中断”出循环。

您正在使用 underscore.js,因此您会很高兴得知它确实提供了一个 every 方法——他们称之为 every,但正如该链接所提到的,它们还提供了一个别名为 all


underscore.js 是否也为此提供了实现?
@FelixKling,是的。我已将其添加到我的答案中。
现在 (05/2013),下划线中的数组既没有 _.every() 也没有 _.all() 方法 - 所以坚持使用 Array.every()
这会起作用,但这是使用 every 的常见原因。所以要注意可读性。
_.each() 的下划线文档专门说明了您无法跳出循环这一事实,并建议您改用 _.find()http://underscorejs.org/#each
N
Nikhil

更新:

_.find 会更好,因为它会在找到元素时跳出循环:

var searchArr = [{id:1,text:"foo"},{id:2,text:"bar"}];
var count = 0;
var filteredEl = _.find(searchArr,function(arrEl){ 
              count = count +1;
              if(arrEl.id === 1 ){
                  return arrEl;
              }
            });

console.log(filteredEl);
//since we are searching the first element in the array, the count will be one
console.log(count);
//output: filteredEl : {id:1,text:"foo"} , count: 1

** 老的 **

如果您想有条件地跳出循环,请使用 _.filter api 而不是 _.each。这是一个代码片段

var searchArr = [{id:1,text:"foo"},{id:2,text:"bar"}];
var filteredEl = _.filter(searchArr,function(arrEl){ 
                  if(arrEl.id === 1 ){
                      return arrEl;
                  }
                });
console.log(filteredEl);
//output: {id:1,text:"foo"}

这不会破坏循环 - 它只是过滤数组。想象一下,数组中没有 2 个而是 20.000 个项目。您的日志只会输出您发布的示例,但循环将运行 20.000 次 :(
@pkyeck 你是对的,可能是 _.find 比 _.filter 更好,因为它在找到元素后会中断,这里是小提琴:jsfiddle.net/niki4810/9K3EV
我认为这个答案应该被标记为正确的。 _.find 完全按照要求执行:遍历列表,直到回调返回 true
投票赞成这个答案,因为接受的答案 (Array.every) 不适用于对象,但 _.find() 会。
这就是文档中推荐的内容:还需要注意的是,不能打破每个循环 - 要打破,请改用 _.find 。
E
Eric

您可以查看 _.some 而不是 _.each。一旦谓词为真,_.some 就会停止遍历列表。结果可以存储在外部变量中。

_.some([1, 2, 3], function(v) {
    if (v == 2) return true;
})

请参阅http://underscorejs.org/#some


R
Rockyboy_ruby
_([1,2,3]).find(function(v){
    return v if (v==2);
})

g
grantwparks

也许你想要 Underscore 的 any() 或 find(),它会在满足条件时停止处理。


c
czizzy

像其他答案一样,这是不可能的。这是关于下划线 underscore issue #21 中断路器的评论


J
JaredMcAteer

您不能在下划线中打断 forEach,因为它模拟 EcmaScript 5 原生行为。


b
bm_i

我相信如果您的数组实际上是一个对象,您可以使用一个空对象返回。

_.({1,2,3,4,5}).each(function(v){  
  if(v===3) return {}; 
});

这只发生在 EcmaScript v < 5 的情况下,因为下划线用于检查您是否在提供的 forEach 替代方案中返回空对象的比较仅在本机对象不可用时进行。
p
percebus

还需要注意的是,不能打破每个循环 - 要打破,请改用 _.find。

http://underscorejs.org/#each


b
bm_i

更新:

实际上,您可以通过在内部抛出错误并在外部捕获它来“中断”:如下所示:

try{
  _([1,2,3]).each(function(v){
    if (v==2) throw new Error('break');
  });
}catch(e){
  if(e.message === 'break'){
    //break successful
  }
}

这显然对您的代码在循环中触发的任何其他异常有一些影响,因此请谨慎使用!


喜欢我如何为此获得如此多的反对票,而这个人的stackoverflow.com/a/2641374/674720获得了很多支持
我参加聚会迟到了,但请注意,那个人不仅说出了你的建议,还提供了另外两种选择(而且更合适)。唯一提供“黑客”以防万一用户想要它。相反,您只提供了丑陋的技巧。
a
aleXela

在我的情况下工作

var arr2 = _.filter(arr, function(item){
    if ( item == 3 ) return item;
});