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

时间:2012-08-09 16:05:27

标签: 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
}

如果您查看 jsFiddle DEMO here ,您会发现速度上的差异与其中任何一个基本相同,但更重要的是我觉得我应该始终< / em>使用for()循环......

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


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

jsFiddle DEMO here

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

只是我的2cents。 :)

6 个答案:

答案 0 :(得分:43)

使用.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
});

I played around with your JSFiddle了解在必须循环遍历原始匹配元素集的子集的情况下,链接如何影响性能。

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

答案 1 :(得分:21)

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

换句话说,这是错误的:

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

每当这些对象中的任何一个在这个循环之后调用它们的“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);
       }); 
   })();
}

正如你所看到的,那就像地狱一样难看,但它应该有效。每个事件处理程序都获得自己的localidx

副本

现在将其与.each()

进行比较
$(someObjectArray).each(function (idx, el) { 
   el.someEventHandler(function(){  
       alert( "this is element " + idx);
   }); 
});

更简单,不是吗?

答案 2 :(得分:9)

jQuery.each vs for-loop

优点jQuery.each:

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

for-loop的优点:

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

示例代码

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

var list = ['a', 'b', 'c', 'd', 'e', 'f'];

jQuery.each:

$.each(list, function(i, v)
{
    // code...
});

没有关闭的For循环:

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

带闭包的For循环:

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

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

答案 3 :(得分:5)

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

答案 4 :(得分:4)

当我找到你的链接时,我得到了两个号码:

$.each() + el(plain JS) 401
for() loop + plainJS[0] iteration   377

如果差异很小,那么选择最具可读性的那个,但是,如果你有非常高的时间要求,那么你可能只需要选择最快的结果。

我建议您编写程序以使用三种不同的方法,上面两种方法,然后使用较新版本的javascript中的foreach,对于那些不支持它的浏览器,您可以将其添加为原型。

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach

您知道您的要求是什么,以及您的计划将做什么,所以只需编写自己的测试并确保它符合您将支持的浏览器的要求。

对于你的第一个问题,我会选择$('element').each因为它更容易阅读,但这只是我的意见。

答案 5 :(得分:1)

实际上$ .each()和$()。each()之间存在很大差异。

根据您传入的内容,它们会略有不同。

http://api.jquery.com/each/ vs http://api.jquery.com/jquery.each/

jquery.each是一个通用迭代器,其中$()。each()特定于jquery集合。

另见:http://jsperf.com/each-vs-each-vs-for-in/9