$ .each () vs for () loop – e desempenho

Estas são principalmente apenas algumas coisas que eu tenho pensado, talvez alguém possa me dar um pouco mais de visão sobre elas, eu vou compartilhar o que eu notei até agora também!

Primeira coisa que eu tenho pensado … existe alguma diferença ou razão para usar:

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

— versus —

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

Olhando para os documentos do jQuery eu não consigo ver nenhuma rima ou razão para um ou outro (talvez você conheça uma instância ou coisas adicionais que uma pessoa pode fazer sobre a outra.

Mas o mais importante é que estou preocupado com a velocidade aqui

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

Se você verificar esta jsFiddle DEMO aqui , você verá que a diferença na velocidade é basicamente equivalente a qualquer um deles, mas o mais importante é que eu sinto que eu deveria estar sempre usando for() loops …

Eu estava apenas testando a unidade (passando por cada uma das 5 funções de cenário diferentes, 50.000 vezes), simplesmente passando por um monte de itens de lista e definindo um data-newAttr , nada de especial.


PERGUNTA :: Eu acho que a minha maior pergunta é, por que não usar sempre loops for ao iterar através de um object? Existe mesmo um ponto para usar $ .each ()? Você sempre usa for () loops mesmo ao passar por objects jQuery?

jsFiddle DEMO aqui

 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 

Apenas meus 2 centavos. 🙂

Uma coisa que .each() permite que você faça isso não pode ser feito com um loop for encadeado .

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

Eu brinquei com seu JSFiddle para ver como o encadeamento influenciaria o desempenho em casos em que você tem que percorrer subconjuntos do conjunto original de elementos correspondentes.

O resultado não foi tão inesperado, embora eu ache que a sobrecarga de end() foi exagerada por causa da combinação de alguns elementos e muitos loops. Além disso: os laços JS simples ainda são um pouco mais rápidos, mas se isso pesa até a legibilidade adicional de .each() (e encadeamento) é discutível.

Uma coisa que você obtém com .each() é o escopo local automático (porque você está invocando uma function anônima para cada object), que por sua vez significa se você está criando ainda mais funções anônimas / closures / event handlers / whatever em cada iteração, você nunca precisa se preocupar com seus manipuladores que compartilham uma variável. Ou seja, o JavaScript não funciona como outras linguagens quando se trata de escopos locais, mas como você pode declarar uma variável em qualquer lugar, ela pode enganá-lo algumas vezes.

Em outras palavras, isso está errado:

 var idx,el; for (idx = 0; idx  

Sempre que algum desses objects invocar seu "someEvent" após este loop (observe que isso é feito), o alerta sempre dirá o último atribuído ao idx , que deve ser (a partir do tempo invocado) someObjectArray.length ;

Para garantir que você salve o índice adequado, é necessário declarar um escopo local, criar uma variável e atribuir a essa variável para uso.

 var idx,el; for (idx = 0; idx  

Como você pode ver, isso é tão feio quanto o inferno, mas deve funcionar. Cada manipulador de events obtém sua própria cópia do localidx

Agora compare isso com .each()

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

Muito mais simples, não é?

jQuery.each vs for-loop

Vantagens jQuery.each:

  • Se encheckbox bem no código jQuery (encadeamento e estilo).
  • Não se preocupe com o escopo (as referências ao iterador e ao object serão persistentes).
  • Pode ser usado universalmente (para todos os tipos de objects e iterando sobre chaves de object).

Vantagens for loop:

  • Alto desempenho (para jogos / animações / grandes conjuntos de dados).
  • Controle total sobre o iterador (ignorar itens, itens de emenda da lista, etc).
  • O loop for sempre funcionará, pois não há dependência no jQuery.
  • Mesma syntax familiar que a maioria dos outros idiomas semelhantes.

Código de exemplo

Este é um exemplo de código de como eu prefiro iterar em uma lista.

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

jQuery.each:

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

For loop sem fechamento:

 for(var i=0,v,n=list.length;i 

For loop com fechamento:

 for(var i=0,n=list.length;i 

Nota: Eu sugiro que você apenas use o loop padrão, e use somente um fechamento quando necessário. No entanto, quando seu código se parece mais com jQuery do que com JavaScript, pode ser mais fácil usar $.each . Em caso de problemas de desempenho, você pode sempre ver isso depois.

Quando fui ao seu link, aqui estão dois números que recebi:

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

Se a diferença for pequena, então vá com a que é mais legível, mas, se você tem requisitos de tempo muito altos, então você só precisa ir com o que acaba sendo o mais rápido.

Eu sugiro que você escreva seu programa para usar três methods diferentes, os dois acima, e então use o foreach encontrado em versões mais novas do javascript e, para aqueles navegadores que não suportam, você pode adicioná-lo como um protótipo.

https://developer.mozilla.org/pt-BR/docs/JavaScript/Reference/Global_Objects/Array/forEach

Você sabe quais são seus requisitos e o que seu programa fará, portanto, basta escrever seus próprios testes e garantir que ele atenda aos requisitos nos navegadores que você estará suportando.

Para a sua primeira pergunta, eu usaria $('element').each , pois é muito mais fácil de ler, mas isso é apenas a minha opinião.

Eu corri alguns testes de desempenho simples, enquanto atrás http://jsperf.com/forloops3 . Parece que ficar com o antigo for loop (onde é possível) é o caminho a seguir 🙂

Na verdade, existe uma grande diferença entre $ .each () e $ (). Each ().

Eles fazem coisas ligeiramente diferentes, dependendo do que você está passando.

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

jquery.each é um iterador genérico, em que $ (). each () é específico de uma coleção jquery.

Veja também: http://jsperf.com/each-vs-each-vs-for-in/9