【问题标题】:how to break the _.each function in underscore.js如何打破 underscore.js 中的 _.each 函数
【发布时间】:2012-02-05 11:29:43
【问题描述】:

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

有没有办法停止下划线 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 来模拟您想要的行为。
  • @Rob。干杯。第一条评论真的很有帮助。事实上,我本来可以用不同的方式来做这件事。

标签: javascript jquery underscore.js


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    您无法脱离 each 方法——它模拟原生 forEach 方法的行为,原生 forEach 不提供转义循环(除了抛出异常)。

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

    从那个链接:

    every 对数组中存在的每个元素执行一次提供的callback 函数,直到找到callback 返回错误值的元素。如果找到这样的元素,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
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

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

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

        【讨论】:

        • 只有在 EcmaScript v
        【解决方案6】:

        更新:

        您实际上可以通过在内部抛出错误并在外部捕获它来“中断”:像这样:

        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 却得到了一大堆的支持
        • 我迟到了,但请注意,那个人不仅说出了你的建议,还提供了另外两种选择(而且更合适)。唯一提供“黑客”以防万一用户想要它。相反,您只提供了丑陋的技巧。
        【解决方案7】:

        更新:

        _.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。这是一个代码sn-p

        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。
        【解决方案8】:
        _([1,2,3]).find(function(v){
            return v if (v==2);
        })
        

        【讨论】:

          【解决方案9】:

          还需要注意的是,不能打破每个循环 - 到 打破,使用 _.find 代替。

          http://underscorejs.org/#each

          【讨论】:

            【解决方案10】:

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

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

            http://underscorejs.org/#some

            【讨论】:

              【解决方案11】:

              在我的情况下工作

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

              【讨论】:

                猜你喜欢
                • 2016-03-01
                • 2013-12-30
                • 2023-03-02
                • 2012-10-24
                • 1970-01-01
                • 2013-01-27
                • 1970-01-01
                • 1970-01-01
                • 2011-04-26
                相关资源
                最近更新 更多