2009-12-10 24 views
32

Estoy haciendo iteraciones muy frecuentes sobre matrices de objetos y he estado usando jQuery.each(). Sin embargo, tengo problemas de velocidad y memoria y uno de los métodos más conocidos según mi perfil es jQuery.each(). ¿Cuál es la palabra en la calle sobre su desempeño? ¿Debería cambiar a un ciclo simple? Por supuesto, estoy arreglando los muchos problemas en mi propio código también.¿Debo usar jQuery.each()?

+2

tenga en cuenta con respecto al generador de perfiles, muchas de las operaciones jQuery integradas hacen uso de $ .each() internamente para realizar su trabajo también. –

+0

es su pregunta sobre jQuery.each() o jQuery(). Each()? .. la primera forma (sobre la que preguntaste) equivale a un bucle for simple. –

+0

El primero. Bueno saber. – pr1001

Respuesta

14

El código fuente de jQuery de cada uno es como sigue (Gracias John Resig y el MIT License):

each: function(object, callback, args) { 
    var name, i = 0, length = object.length; 

    if (args) { 
     if (length === undefined) { 
      for (name in object) 
       if (callback.apply(object[ name ], args) === false) 
        break; 
     } else 
      for (; i < length;) 
       if (callback.apply(object[ i++ ], args) === false) 
        break; 

    // A special, fast, case for the most common use of each 
    } else { 
     if (length === undefined) { 
      for (name in object) 
       if (callback.call(object[ name ], name, object[ name ]) === false) 
        break; 
     } else 
      for (var value = object[0]; 
       i < length && callback.call(value, i, value) !== false; value = object[++i]){} 
    } 

    return object; 
} 

Como se puede rastrear y ver, en la mayoría de los casos se utiliza un básico de bucle donde la única sobrecarga realmente es solo la devolución de llamada en sí misma. No debería hacer una diferencia en el rendimiento.

EDITAR: Esto es con la constatación de que la tara del selector ya se ha producido y se le da una matriz poblada object.

+4

¿Has usado IE6? – ChaosPandion

+0

Por supuesto. Y como la mayoría de nosotros lamentablemente, así. ¿Pero cuál es tu punto específicamente? Mi punto es que el corazón de "cada" es solo un ciclo. Dejé la sobrecarga que se obtiene al instanciar un objeto jQuery y seleccionar solo elementos dom. –

+4

Lo que estoy diciendo es que no subestimes la sobrecarga de llamadas a funciones. – ChaosPandion

6

Una forma de asegurarse de obtener el máximo provecho de jquery es almacenar la matriz devuelta de resultados en una variable en lugar de volver a recorrer el DOM cada vez que necesite obtener algo.

ejemplo de qué no hacer:

$('.myLinks').each(function(){ 
    // your code here 
}); 
$('.myLinks').each(function(){ 
    // some more code here 
}); 

Mejor práctica:

var myLinks = $('.myLinks'); 
myLinks.each(function(){ 
    // your code here 
}); 
myLinks.each(function(){ 
    // some more code here 
}); 
+17

Mejor práctica: haz todo en un ciclo. – ChaosPandion

+0

Seguramente ambos ejemplos son los mismos si se ejecutó una vez? Antes de que jQuery repita el objeto, configura una variable, tal como lo hace en su segundo ejemplo. Si tuviera que ejecutar la instrucción '.each' varias veces, entonces quizás almacenar en caché la variable ayudaría. –

5

Este método debería darle una mejora dramática velocidad.

var elements = $('.myLinks').get(), element = null; 
for (var i = 0, length = elements.length; i < length; i++) { 
    element = elements[i]; 
    element.title = "My New Title!"; 
    element.style.color = "red"; 
} 

El almacenamiento en memoria caché también mejorará el rendimiento.

function MyLinkCache() { 
    var internalCache = $('.myLinks').get(); 

    this.getCache = function() { 
     return internalCache; 
    } 

    this.rebuild = function() { 
     internalCache = $('.myLinks').get(); 
    } 
} 

En uso:

var myLinks = new MyLinkCache(); 

function addMyLink() { 
    // Add a new link. 
    myLinks.rebuild(); 
} 

function processMyLinks() { 
    var elements = myLinks.getCache(), element = null; 
    for (var i = 0, length = elements.length; i < length; i++) { 
     element = elements[i]; 
     element.title = "My New Title!"; 
     element.style.color = "red"; 
    } 
} 
26

This article (# 3) corrió algunas pruebas de rendimiento y se encontró que la función jQuery .Cada era aproximadamente 10 veces tan lento como el Javascript nativo para bucle.

De 10 Ways to Instantly Increase Your jQuery Performance - 3. Use For Instead of Each
Usando Firebug, es posible medir el tiempo de cada una de las dos funciones se necesita para ejecutar.

var array = new Array(); 
for (var i=0; i<10000; i++) { 
    array[i] = 0; 
} 

console.time('native'); 
var l = array.length; 
for (var i=0;i<l; i++) { 
    array[i] = i; 
} 
console.timeEnd('native'); 

console.time('jquery'); 
$.each (array, function (i) { 
    array[i] = i; 
}); 
console.timeEnd('jquery'); 

Los resultados anteriores son de 2 ms para código nativo, y 26 ms para "cada" método de jQuery. Siempre que lo probé en mi máquina local y que en realidad no están haciendo nada (solo una mera operación de llenado de matriz), cada función de jQuery toma más de 10 veces más tiempo que el ciclo "para" nativo de JS. Esto ciertamente aumentará cuando se trate de cosas más complicadas, como establecer atributos CSS u otras operaciones de manipulación de DOM.

+2

Gracias, es un buen artículo. – pr1001

+0

esto debería ser una respuesta. mis páginas dinámicas estaban entrecortadas solo por 'cada'. también, el enlace proporciona buenos consejos. Me acabo de dar cuenta de que solo estoy haciendo un 40% –

+1

Si bien esta respuesta tiene más de un año de antigüedad y el enlace es útil, sería mejor si publicas las partes esenciales de la respuesta aquí, en este sitio, o tu publicación corre el riesgo de ser eliminada [ Consulte las Preguntas frecuentes donde se mencionan las respuestas que son 'apenas más que un enlace'.] (Http://stackoverflow.com/faq#deletion) Puede incluir el enlace si lo desea, pero solo como 'referencia'. La respuesta debería ser independiente sin necesidad del enlace. – Taryn

6

El uso de la funcionalidad nativa generalmente será más rápido que una abstracción, como el método JQuery.each(). Sin embargo, el método JQuery.each() es más fácil de usar y requiere menos codificación de su parte.

A decir verdad, ninguna es la elección correcta o incorrecta sin contexto. Soy de la opinión de que deberíamos escribir código más fácil primero, suponiendo que es bueno/legible/código limpio. Si se encuentra en una situación, como la que está describiendo, donde hay un retraso notable, entonces es hora de averiguar dónde están sus cuellos de botella y escribir un código más rápido.

Sustitución del método JQuery.each() en estos escenarios podría ayuda, sin embargo, no haber visto su código, es posible que usted tiene cuellos de botella no relacionadas con el método jQuery.