$ .each()vs()循环 – 和性能
这些主要是我一直想知道的一些事情,也许有人可以给我更多的洞察力,我会分享我迄今为止注意到的!
我一直想知道的第一件事是…有没有什么区别好或理由使用:
$('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()
循环。
我只是unit testing(遍历5个不同场景函数的每一个,5万次),简单地遍历一堆列表项,并设置一个data-newAttr
,没有什么特别的。
问题:我想我最大的问题是,为什么不在迭代通过对象时总是使用循环? 甚至有点使用$ .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
只是我的2cents。 🙂
有一件事.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()
的开销在这里被夸大了,因为less数元素和很多循环的结合。 除此之外:普通的JS循环仍然稍微快一点,但是是否会影响到.each()
(和链接)的附加可读性是值得商榷的。
你使用.each()
所做的一件事就是自动本地范围确定(因为你为每个对象调用一个匿名函数),这意味着如果你在每次迭代中创build更多的匿名函数/闭包/事件处理器/你永远不用担心你的处理程序共享一个variables。 也就是说,当涉及到本地范围时,JavaScript并不像其他语言那样行事,但是由于您可以在任何地方声明一个variables,它有时可能会欺骗您。
换句话说,这是错误的:
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
;
为了确保保存正确的索引,必须声明一个本地作用域,创build一个variables并分配给该variables以供使用。
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); }); });
简单得多,不是吗?
jQuery.each与for循环
好处jQuery.each:
- 适合jQuery代码(链接和样式)。
- 不用担心范围(对迭代器和对象的引用将是持久的)。
- 可以普遍使用(用于各种对象并遍历对象键)。
for-loop的优点:
- 高性能(游戏/animation/大型数据集)。
- 完全控制迭代器(跳过项目,从列表拼接项目等)。
- for循环将始终工作,因为不依赖于jQuery。
- 与大多数其他类似语言一样熟悉的语法。
示例代码
这是我更喜欢迭代列表的示例代码。
var list = ['a', 'b', 'c', 'd', 'e', 'f'];
jQuery.each:
$.each(list, function(i, v) { // code... });
没有closures的循环:
for(var i=0,v,n=list.length;i<n;i+=1) { v = list[i]; // code... }
闭环闭环:
for(var i=0,n=list.length;i<n;i+=1) { (function(i, v) { // code... })(i, list[i]); }
注意:我build议你只使用标准的for-loop,并且只在必要的时候使用闭包。 然而,无论如何,当你的代码看起来比jQuery更像jQuery时,使用$.each
可能会更容易$.each
。 如果出现性能问题,可以随时查看。
当我去你的链接这里有两个数字,我得到了:
$.each() + el(plain JS) 401 for() loop + plainJS[0] iteration 377
如果差距很小,那就select一个最具可读性的区域,但是如果时间要求非常高的话,那么你可能只需要以最快的速度进行。
我build议你编写你的程序,使用三种不同的方法,上面的两个,然后使用新版本的JavaScript中find的foreach,对于那些不支持它的浏览器,你可以添加它作为原型。
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach
你知道你的要求是什么,你的程序会做什么,所以只需编写你自己的testing,并确保它符合你将要支持的浏览器的要求。
对于你的第一个问题,我会去$('element').each
因为它更容易阅读,但这只是我的看法。
我之前运行了一些简单的性能testinghttp://jsperf.com/forloops3 。 似乎坚持平原,旧for loop
(这是可能的)是要走的路:)
实际上$ .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