75

这些主要只是我一直想知道的一些事情,也许有人可以给我更多的见解,我也会分享我到目前为止所注意到的!

我一直想知道的第一件事......有什么好的或理由使用的区别:

$('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,你会发现速度上的差异基本上与它们中的任何一个相同,但更重要的是我觉得我应该总是使用for()循环......

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


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

jsFiddle 演示在这里

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

只是我的2美分。:)

4

6 回答 6

48

允许您执行循环.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
});

我玩弄了您的JSFiddle,以了解在您必须遍历原始匹配元素集的子集的情况下,链接将如何影响性能。

结果并没有那么出乎意料,尽管我认为end()这里的开销被夸大了,因为元素少,循环多。除此之外:普通的 JS 循环仍然稍微快一些,但这是否与增加的.each()(和链接)的可读性有关还有待商榷。

于 2012-08-09T16:11:43.277 回答
22

你得到的一件事.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);
   }); 
});

简单很多,不是吗?

于 2012-08-09T16:28:53.167 回答
9

jQuery.each 与 for 循环

jQuery.each 的优点:

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

for循环的优点:

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

示例代码

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

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

jQuery.每个:

$.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. 如果出现性能问题,您可以随时查看它。

于 2014-09-10T22:56:01.013 回答
5

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

于 2012-12-28T20:04:01.243 回答
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因为它更容易阅读,但这只是我的意见。

于 2012-08-09T16:17:38.540 回答
2

实际上 $.each() 和 $().each() 之间有很大的区别。

根据您传入的内容,它们会做些许不同的事情。

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

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

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

于 2013-10-24T00:26:23.230 回答