$ .each()vs for()循环 - 和性能

Mar*_*.io 68 javascript jquery

这些主要是我一直想知道的一些事情,也许有人可以给我一些关于它们的更多见解,我将分享到目前为止我已经注意到的内容!

我一直在想的第一件事......是否有任何不同的好处或理由使用:

$('element').each(function (i, el) { });

- 与 -

$.each($('element'), function (i, el) { });

看看jQuery文档,我看不出任何一个或另一个的押韵或理由(也许你知道一个实例或其他东西可以做的另一个.

但更重要的是我在这里关注速度

// As opposed to $.each() looping through a jQuery object
// -- 8x faster 
for (var i = 0, $('.whatever').length; i < len; i++) {
    $('.whatever')[i] // do stuff
}
Run Code Online (Sandbox Code Playgroud)

如果你在这里查看这个jsFiddle DEMO,你会发现速度的差异基本上与它们中的任何一个相同,但更重要的是我觉得我应该总是使用for()循环...

我只是单元测试(循环遍历5个不同的场景函数中的每一个,50,000次),简单地循环遍历一堆列表项,并设置一个data-newAttr,没什么特别的.


问题::我想我最大的问题是,为什么不总是在迭代对象时使用for循环?是否有使用$ .each()的意义?即使在浏览jQuery对象时,你总是使用for()循环吗?

jsFiddle DEMO在这里

Function type:                  Execution Time:
_testArea.each() + $(this)               1947   <-- using $(this) slows it down tremendously
$.each()         + $(this)               1940
_testArea.each() + el(plain JS)           458   <-- using the Element speeds things up
$.each()         + el(plain JS)           452
for() loop       + plainJS[0] iteration   236   <-- over 8x faster
Run Code Online (Sandbox Code Playgroud)

只是我的2cents.:)

PPv*_*PvG 46

.each()允许你这样做的一件事是for循环不能完成链接.

$('.rows').each(function(i, el) {
    // do something with ALL the rows
}).filter('.even').each(function(i, el) {
    // do something with the even rows
});
Run Code Online (Sandbox Code Playgroud)

我和你的JSFiddle一起,看看在必须循环遍历原始匹配元素集的子集的情况下,链接如何影响性能.

结果并不是那么出乎意料,尽管我认为end()这里的开销因为少数元素和许多循环的组合而被夸大了.除此之外:普通的JS循环仍然稍微快一点,但是否能够增加.each()(和链接)的可读性是值得商榷的.


Jay*_*ayC 21

你要做的一件事.each()是自动本地作用域(因为你正在为每个对象调用一个匿名函数),这反过来意味着如果你在每次迭代中创建更多的匿名函数/闭包/事件处理程序/什么,你永远不必担心你的处理程序共享一个变量.也就是说,当涉及本地范围时,JavaScript不像其他语言一样,但是因为你可以在任何地方声明变量,它有时会欺骗你.

换句话说,这是错误的:

var idx,el;
for (idx = 0; idx <someObjectArray.length; idx++){
   el = someObjectArray[idx]
   el.someEventHandler(function(){  
       alert( "this is element " + idx);
   }); 
}
Run Code Online (Sandbox Code Playgroud)

每当这些对象中的任何一个在这个循环之后调用它们的"someEvent"时(请注意这个被组成),警告总是会说出最后分配的内容idx,应该是(截至调用的时间)someObjectArray.length;

要确保保存正确的索引,必须声明本地范围,创建变量并分配给该变量以供使用.

var idx,el;
for (idx = 0; idx <someObjectArray.length; idx++){
   el = someObjectArray[idx];
   (function(){
       var localidx = idx;
       el.someEventHandler(function(){  
           alert( "this is element " + localidx);
       }); 
   })();
}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,那就像地狱一样丑陋,但它应该有效.每个事件处理程序都有自己的副本localidx

现在比较一下 .each()

$(someObjectArray).each(function (idx, el) { 
   el.someEventHandler(function(){  
       alert( "this is element " + idx);
   }); 
});
Run Code Online (Sandbox Code Playgroud)

简单多了,不是吗?


Yet*_*eti 9

jQuery.each vs for-loop

优点jQuery.each:

  • 适合jQuery代码(链接和样式).
  • 不用担心范围(对迭代器和对象的引用将是持久的).
  • 可以普遍使用(用于所有类型的对象并迭代对象键).

循环的优点:

  • 高性能(适用于游戏/动画/大型数据集).
  • 完全控制迭代器(跳过项目,从列表中拼接项目等).
  • for循环将始终有效,因为它不依赖于jQuery.
  • 与大多数其他类似语言一样熟悉的语法.

示例代码

这是我更喜欢迭代列表的示例代码.

var list = ['a', 'b', 'c', 'd', 'e', 'f'];
Run Code Online (Sandbox Code Playgroud)

jQuery.each:

$.each(list, function(i, v)
{
    // code...
});
Run Code Online (Sandbox Code Playgroud)

没有闭包的For循环:

for(var i=0,v,n=list.length;i<n;i+=1)
{
    v = list[i];
    // code...
}
Run Code Online (Sandbox Code Playgroud)

带闭包的For循环:

for(var i=0,n=list.length;i<n;i+=1)
{
    (function(i, v)
    {
        // code...
    })(i, list[i]);
}
Run Code Online (Sandbox Code Playgroud)

注意:我建议您只使用标准for循环,并在必要时仅使用闭包.但是,当你的代码看起来更像jQuery而不是Javascript时,它可能更容易使用$.each.如果出现性能问题,您可以随时查看.


op1*_*kun 5

我在http://jsperf.com/forloops3之前运行了一些简单的性能测试.似乎坚持平原,旧for loop(可能的地方)是要走的路:)