2013-06-12 27 views
7

首先,一些伪伪代码:

$("some-selector-logic").each(function() { 
    if (someLogic($(this))) { 
    return false; 
    } 
    // Otherwise do stuff related to $(this) 
}); 

someMoreExcitingCode(); 

在这个例子中,我们基于一些选择逻辑得到DOM元素的集合,然后再遍历各一个。对于我们要求的每个元素someLogic()。如果返回true我们中止每个循环。否则,我们对元素执行一些逻辑,然后继续下一个元素。一旦我们完成了所有我们继续的内容并致电someMoreExcitingCode()

在致电someMoreExcitingCode()之前,我想知道该环路是否过早中止。很明显,你可以做这样的事情:

var aborted = false; 
$("..").each(function() { 
    if (someLogic($(this))) { 
    aborted = true; 
    return false; 
    } 
}); 

但这种感觉马虎对我来说,像jQuery应该给我提供了另一种方式这一信息。有没有更实用的方式来达到我不知道的目的?

+0

我还没有遇到任何其他方式来解决这个问题 –

+0

为什么你需要知道?我从来没有亲自跑过这样的要求,乍一看它脱落为臭/泄漏。也许有更好的方法来解决你正在处理的更大的问题。 –

+0

我想你已经拥有的是一个变体,但是我没有看到你已经拥有的优势 – TGH

回答

3

由于jQuery函数倾向于返回它们被调用的对象集合(以允许链接),因此each()函数无法将该信息返回给您 - 它已经返回了一个jQuery对象可以链接其他方法调用。

根据您提供的信息,我没有看到使用外部标志或计数器变量来获取此信息的问题。如果你告诉我们更多关于为什么你需要知道这一点,但我们可能会提供更多有用的建议。

2

$.each()没什么神奇的。这是一个简单的功能,它可以满足您的需求,也可以满足您的需求。如果没有,那么在代码示例中设置变量没有任何问题。编写自己的each()函数完全符合您的需求并没有错。这只是几行代码,它会运行一个循环并调用您的回调函数。

下面是jQuery的1.10.1为$.each()的源代码:

// args is for internal usage only 
each: function(obj, callback, args) { 
    var value, 
     i = 0, 
     length = obj.length, 
     isArray = isArraylike(obj); 

    if (args) { 
     if (isArray) { 
      for (; i < length; i++) { 
       value = callback.apply(obj[ i ], args); 

       if (value === false) { 
        break; 
       } 
      } 
     } else { 
      for (i in obj) { 
       value = callback.apply(obj[ i ], args); 

       if (value === false) { 
        break; 
       } 
      } 
     } 

    // A special, fast, case for the most common use of each 
    } else { 
     if (isArray) { 
      for (; i < length; i++) { 
       value = callback.call(obj[ i ], i, obj[ i ]); 

       if (value === false) { 
        break; 
       } 
      } 
     } else { 
      for (i in obj) { 
       value = callback.call(obj[ i ], i, obj[ i ]); 

       if (value === false) { 
        break; 
       } 
      } 
     } 
    } 

    return obj; 
}, 

此代码中的唯一的复杂性来自其处理对象和数组,有两种不同的情况为每个的事实。

为你处理的情况下,把它归结为:

 for (; i < length; i++) { 
      value = callback.call(obj[ i ], i, obj[ i ]); 

      if (value === false) { 
       break; 
      } 
     } 

只是有没有那么多的代码那里,如果你想要的东西没有做,你可以很容易地编写自己相似迭代器,它完全符合你的需求。

你甚至可以使用简单的for循环。

function doExcitingStuff() { 
    var $elements = $("some-selector-logic"); 
    for(var i = 0; i < $elements.length; i++) { 
     var $element = $($elements[i]); 
     if(someLogic($element)) 
      return; 
     // Otherwise do stuff related to $element 
    } 
    someMoreExcitingCode(); // only runs if the loop completes 
} 

这一切都取决于什么让你的代码最干净。您可以使用$.each()或编写自己的。

0

也许不是优雅如你所愿,但你可以使用Array.prototype.some

var aborted = Array.prototype.some.call($(".foo"), function(el) { 
    if ($(el).hasClass('bar')) { 
     return true; 
    } 
}); 

jsfiddle

0

如果你真的想避免这种abort布尔,你关心的不是效率,那么你可以这样做:

$("..").removeClass('aborted').each(function() { 
    if(someLogic($(this))) { 
     $(this).addClass('aborted'); 
     return false; 
    } 
}); 

if($("..").find('aborted').length) { 
    //each was aborted 
} 
else { 
    //each ran to completion 
} 

但是,这是有效地使用DOM来注册你的布尔状态,而不是设置一个JS变种。

就我个人而言,我会硬着头皮用你的abort = true的想法。

相关问题