Que soy un fan de jQuery no es una novedad, pero si que es una novedad el que no lo uso de la forma más correcta. Por lo menos así lo ven la gente de ArtzStudio, que nos muestran una serie de indicaciones con el fin de optimizar el uso del CPU el usuario mejorando el rendimiento de nuestros scripts.
1) Siempre desciende desde un #ID
Siempre el selector más rápido y que menos iteraciones produce es la búsqueda por un #id
, ya que simplemente lanza un document.getElementById()
, lo que al ser nativo nos asegura un tiempo de respuesta mínimo y un mínimo consumo de proceso.
<div id="content">
<form method="post" action="/">
<h2>Traffic Light</h2>
<ul id="traffic_light">
<li><input type="radio" class="on" name="light" value="red" /> Red</li>
<li><input type="radio" class="off" name="light" value="yellow" /> Yellow</li>
<li><input type="radio" class="off" name="light" value="green" /> Green</li>
</ul>
<input class="button" id="traffic_button" type="submit" value="Go" />
</form>
</div>
Con el código anterior, si queremos coger el elemento #traffic_button
, siempre nos será más rápido hacerlo directamente que medainte la class del mismo elemento.
// Más lento
var traffic_button = $('#content .button');
// Más rápido
var traffic_button = $('#traffic_button');
Seleccionar varios elementos
Si por contra, necesitamos seleccionar una serie de elementos, siempre que podamos debemos hacerlo partiendo de un #id
, de esta forma nos aseguramos una iteración más ajustada.
var traffic_lights = $('#traffic_light input');
Aclaración
Hay que destacar que esto afectará positivamente al rendimiento, aunque el uso de selectores más complejos permiten mejorar la flexibilidad de nuestros scripts. Es importante tener en cuenta esta recomendación, pero no se puede aplicar a todos los casos.
2) Usa tags delante de las clases
Al contrario que con el #id
, en el que se innecesario indicar el tag asociado a ese #id
(div#page
), esto no tiene sentido y además penaliza a lo que comentamos en el punto 1. En la selección de clases, es recomendable indicar el tag del elemento solicitado ya que al hacer uso de document.getElementsByTagName()
para localizarlos acotamos previamente los elementos en los que buscar las clases solicitadas. Con el mismo código:
<div id="content">
<form method="post" action="/">
<h2>Traffic Light</h2>
<ul id="traffic_light">
<li><input type="radio" class="on" name="light" value="red" /> Red</li>
<li><input type="radio" class="off" name="light" value="yellow" /> Yellow</li>
<li><input type="radio" class="off" name="light" value="green" /> Green</li>
</ul>
<input class="button" id="traffic_button" type="submit" value="Go" />
</form>
</div>
Si queremos seleccionar el elemento radio con class on, la opción rápida sería la siguiente:
var active_light = $('#traffic_light input.on');
3) Usa la caché de objetos
Coger el hábito de guardar una variable con el valor de un objeto jQuery nos evita realizar una serie de comprobaciones innecesarias y que en scripts pesados pueden suponer un aumento de rendimiento preocupante.
// NO
$('#traffic_light input.on).bind('click', function(){...});
$('#traffic_light input.on).css('border', '3px dashed yellow');
$('#traffic_light input.on).css('background-color', 'orange');
$('#traffic_light input.on).fadeIn('slow');
// SI
var $active_light = $('#traffic_light input.on');
$active_light.bind('click', function(){...});
$active_light.css('border', '3px dashed yellow');
$active_light.css('background-color', 'orange');
$active_light.fadeIn('slow');
4) Aprovechate del encadenamiento
El encadenamiento pese a producir un amasijo de código que no contribuye a mejorar la lectura del código hace que nuestro Javascript sea más ligero y puede ayudar a mejorar el rendimiento de nuestros scritps. Veamos el ejemplo anterior:
var $active_light = $('#traffic_light input.on');
$active_light.bind('click', function(){...})
.css('border', '3px dashed yellow')
.css('background-color', 'orange')
.fadeIn('slow');
5) Usa subqueries siempre que puedas.
Si debemos realizar varias búsquedas sobre un elemento es altamente recomendable realizar un uso intensivo del método find()
de jQuery para realizar las búsquedas. Mejoraremos el tiempo de respuesta al evitarnos búsquedas previas ya realizadas.
Usando el código HTML anterior podemos hacer lo siguiente:
var $traffic_light = $('#traffic_light'),
$active_light = $traffic_light.find('input.on'),
$inactive_lights = $traffic_light.find('input.off');
6) Limita la manipulación de DOM
Ya vimos hace un tiempo que la manipulación directa del arbol DOM es muy costoso y lento. Por eso el limitar el uso de esta técnica nos favorecerá a la hora de procesar nuestros scripts.
// Más lento
var top_100_list = [...], // assume this has 100 unique strings
$mylist = $('#mylist'); // jQuery selects our <ul> element
for (var i=0, l=top_100_list.length; i<l; i++) {
$mylist.append('<li>' + top_100_list[i] + '</li>');
}
// Más rápido
var top_100_list = [...], // assume this has 100 unique strings
$mylist = $('#mylist'), // jQuery selects our <ul> element
top_100_li = ""; // This will store our list items
for (var i=0, l=top_100_list.length; i<l; i++){
top_100_li += '<li>' + top_100_list[i] + '</li>';
}
$mylist.html(top_100_li);
7) Aprovechate de la delegación de eventos
Mientras no se diga lo contrario los eventos se propagan hasta el elemento padre. Esto tiene una utilidad realmente interesante y nos puede ayudar a evitar tener que realizar busquedas muy concretas.
// Menos eficiente
$('#entryform input).bind('focus', function(){
$(this).addClass('selected');
}).bind('blur', function(){
$(this).removeClass('selected');
});
// Más eficiente
$('#entryform).bind('focus', function(e){
var cell = $(e.target); // e.target almacena el nodo que ha lanzado el evento.
cell.addClass('selected');
}).bind('blur', function(e){
var cell = $(e.target);
cell.removeClass('selected');
});
8 ) Elimina consultas innecesarias
Prácticamente todos los puntos anteriores, nos dan soluciones para realizar el mínimo de consultas posibles realizando las mismas funciones. Pero este punto ataca más directamente a llamadas innecesarias como por ejemplo el $(document).ready();
que podemos evitar.
// Menos eficiente
$(document).ready(function(){
mylib.article.init();
});
// Más eficiente
<script type="text/javascript>
mylib.article.init();
</script>
</body>
Como vemos la clave está en lanzar el <script />
justo antes de cerrar el tag </body>
lo que nos asegura que todos los elementos que podemos necesitar están ya cargados en el árbol DOM.
9) Piensa en usar $(window)load()
Aunque $(document).ready()
es muy útil y potente, no espera a que se carguen todos los elementos (imagenes, flash,..) para ejecutarse. Lo que puede producir un problema ya que está cargando nuestros scripts y además el navegador está trabajando en mostrar por pantalla otros elementos.
En estos casos, quizas nos sería conveniente usar $(window).load()
.
$(window).load(function(){
...
});
Esta función, esperará a cargar toda la página (imagenes, flash,…) incluidos, para lanzar nuestros scripts.
10) Comprime tu código
Este punto es discutible ya que al comprimir tu código estás haciendo que el navegador del usuario lo haya de descomprimir, lo que puede incrementar el rendimiento requerido frente a la velocidad de carga del script. Es interesnate tener en cuenta los factores que intervienen para decidir que acción realizar.
11) Aprenderte la librería
A estas alturas seguro que ya la conoces, pero no está de más tener a mano alguna Cheat Sheet(.pdf) para evitar caer en soluciones poco optimizadas.
12) Usa html() con cabeza
Como nos recuenda Joseanpg en los comentarios, el uso de html()
nos penaliza sustancialmente el rendimiento de nuestros scripts. jQuery, al contrario de MooTools y Prototype (no he mirado los demás) no injecta el código HTML mediante innerHTML, sinó que construye los elementos DOM
y los añade al nodo indicado.
Este proceso es más lento que usar un simple innerHTML
aunque nos puede provocar problemas en insercciones en las que necesitemos refrescar el arbol DOM
.
En la mayoría de casos, la mejor opción es usar innerHTML
en nuestros scripts ya que añaden elementos perfectamente a nuestro arbol DOM
y es realmente rápido. Para todo lo demás, html()
.
18 comentarios, 5 referencias
+
#