Best practice per migliorare le prestazioni
Indice
Questo capitolo tratta molte migliori pratiche JavaScript e jQuery, senza un particolare ordine.
Molte di queste pratiche si basano sulla presentazione jQuery Anti-Patterns for Performance (in inglese) di Paul irlandese.
Salva la lunghezza del loops
⤽
In un ciclo, è necessario accedere alla lunghezza di un array ogni volta che viene valutata la condizione; tale valore può essere memorizzato in anticipo in una variabile.
Aggiungere nuovi contenuti fuori da un ciclo
Copia codice
var myLength = myArray.length;
for (var i = 0; i < myLength; i++) {
// fare delle cose
}
⤽
Se si sta inserendo molti elementi nel DOM, fatelo tutti in una volta, non uno per volta.
Non Ripetersi
Copia codice
// male
$.each(myArray, function(i, item) {
var newListItem = '<li>' + item + '</li>';
$('#ballers').append(newListItem);
});
// meglio: fare questo
var frag = document.createDocumentFragment();
$.each(myArray, function(i, item) {
var newListItem = '<li>' + item + '</li>';
frag.appendChild(newListItem);
});
$('#ballers')[0].appendChild(frag);
// o questo
var myHtml = '';
$.each(myArray, function(i, item) {
html += '<li>' + item + '</li>';
});
$('#ballers').html(myHtml);
⤽
Nessuna ricorrenza; fare le cose una volta e solo una, altrimenti è sbagliato.
Attenzione alle funzioni anonime
Copia codice
// MALE
if ($eventfade.data('currently') != 'showing') {
$eventfade.stop();
}
if ($eventhover.data('currently') != 'showing') {
$eventhover.stop();
}
if ($spans.data('currently') != 'showing') {
$spans.stop();
}
// BENE
var $elems = [$eventfade, $eventhover, $spans];
$.each($elems, function(i,elem) {
if (elem.data('currently') != 'showing') {
elem.stop();
}
});
⤽
Non è consigliabile utilizzare abbondantemente le funzioni anonime. Queste sono difficili da eseguire in debug, per la manutenzione, il test e suo riutilizzo. Al suo posto, utilizzare un valore letterale per organizzare e nominare i suoi controllori e le funzioni di retrochiamata (callback).
Ottimizzazione dei selettori
Copia codice
// MALE
$(document).ready(function() {
$('#magic').click(function(e) {
$('#yayeffects').slideUp(function() {
// ...
});
});
$('#happiness').load(url + ' #unicorns', function() {
// ...
});
});
// MEGLIO
var PI = {
onReady : function() {
$('#magic').click(PI.candyMtn);
$('#happiness').load(PI.url + ' #unicorns', PI.unicornCb);
},
candyMtn : function(e) {
$('#yayeffects').slideUp(PI.slideCb);
},
slideCb : function() { ... },
unicornCb : function() { ... }
};
$(document).ready(PI.onReady);
⤽
L’ottimizzazione dei selettori è meno importante di una volta, grazie all’implementazione in alcuni browser web document.querySelectorAll(), passando il peso di jQuery verso browser web. Tuttavia, ci sono alcuni consigli da tenere a mente.
Selettori basati sugli ID
Utilizzare la delegazione di Eventi Selettori basati sugli ID
⤽
È sempre meglio iniziare le selezioni con un ID.
L’esempio che utilizza
Specificità
Copia codice
// veloce
$('#container div.robotarm');
// super-veloce
$('#container').find('div.robotarm');
$.fn.find
è più veloce perché la prima selezione utilizza il motore di selezione interno Sizzle -. Mentre la selezione realizzata unicamente per ID utilizza document.getElementById()
, che è estremamente veloce grazie alla è una funzione nativa del browser web.⤽
Cercate di essere specifico per il lato destro della selezione e meno specifici per il sinistro.
Utilizzare il più possibile tag.classe del lato destro della selezione, e solo tag o .classe a sinistra.
La seconda selezione ha prestazioni migliori perché attraversa meno strati per individuare l’elemento.
Evitare il selettore universale
Copia codice
// non ottimizzato
$('div.data .gonzalez');
// ottimizzato
$('.data td.gonzalez');
Evitare specificità eccessiva
Copia codice
$('.data table.attendees td.gonzalez');
// molto meglio: eliminare il mezzo, se possibile,
$('.data td.gonzalez');
⤽
Selezioni dove si specifica implicita o esplicitamente una selezione universale che può essere molto lento.
Copia codice
$('.buttons > *'); // molto lento
$('.buttons').children(); // molto meglio
$('.gender :radio'); // selezione universale implicita
$('.gender *:radio'); // stesa cosa, ma in modo esplicito
$('.gender input:radio'); // molto meglio
⤽
La delega di eventi permette vincolare un gestore eventi a un elemento contenitore (per esempio, una lista non ordinata) in luogo di molteplici elementi contenuti (per esempio, gli elementi in una lista). jQuery rende rende questo lavoro facile attraverso $.fn.live e $.fn.delegate. Se possibile, si raccomanda utilizzare $.fn.delegate anziché $.fn.live, giacché elimina la necessità di una selezione e il suo contesto esplicito riduce il carico di circa il 80%.
Separare elementi per lavorare con loro Inoltre, la delegazione di eventi permette di aggiungere nuovi elementi contenitori alla pagina, senza dover vincolare i loro gestori di eventi.
Copia codice
// sbagliato (se ci sono molti elementi nella lista)
$('li.trigger').click(handlerFn);
// meglio: delegazione di eventi con $ fn.live.
$('li.trigger').live('click', handlerFn);
// molto meglio:. delegazione di evento con $ fn.delegate
// permette specificare un contesto in modo facile
$('#myList').delegate('li.trigger', 'click', handlerFn);
⤽
Se possibile, evitare la manipolazione del DOM. Per contribuire a questo scopo, dalla versione 1.4 jQuery introduce $.fn.detach il quale permette lavorare con gli elementi del DOM in forma separata per poi inserirli.
Utilizzare stili a cascata per modificare il Css tra vari elementi
Copia codice
var $table = $('#myTable');
var $parent = $table.parent();
$table.detach();
// ... si aggiungono molte celle alla tabella
$parent.append($table);
⤽
Se si modifica il CSS in più di 20 elementi con $.fn.css, considerate le modifiche agli stili con l’aggiunta di un tag style. Ciò consentirà di aumentare le prestazioni del 60%.
Utilizzare $.data anziché $.fn.data
Copia codice
// corretto fino a 20 elementi, lento dopo i 20 elementi
$('a.swedberg').css('color', '#asd123');
$('<style type="text/css">a.swedberg { color : #asd123 }</style>')
.appendTo('head');
⤽
Utilizzare $.data in un elemento DOM invece di $.fn.data in una selezione può essere fino a 10 volte più veloce. Prima di farlo, assicuratevi di capire la differenza tra un elemento DOM e una selezione jQuery.
Non agire su elementi inesistenti
Copia codice
// regolare
$(elem).data(key,value);
// 10 volte più veloce
$.data(elem,key,value);
⤽
jQuery non ci dirà se si cerca di eseguire un codice su una selezione vuota – questo verrà eseguito come se nulla fosse. Dipende da noi vedere se la selezione contiene elementi.
Questo consiglio è particolarmente adatto per i widget jQuery UI, i quali hanno un carico pesante, anche quando la selezione non contiene elementi.
Definizione di variabili
Copia codice
// SBAGLIATO: il codice esegue tre funzioni
// senza verificare se ci sono
// nella selezione
$('#nosuchthing').slideUp();
// MEGLIO
var $mySelection = $('#nosuchthing');
if ($mySelection.length) { $mySelection.slideUp(); }
// MOLTO MEGLIO: aggiunge una estensione doOnce
jQuery.fn.doOnce = function(func){
this.length && func.apply(this);
return this;
}
$('li.cartitems').doOnce(function(){
// fare qualcosa
});
⤽
Le variabili possono essere definite in una unica dichiarazione, invece di più volte.
Nelle funzioni di autoeseguibili, le definizioni di variabili possono essere passate tutte insieme.
Condizionali
Copia codice
// antico
var test = 1;
var test2 = function() { ... };
var test3 = test2(test);
// migliore modo
var test = 1,
test2 = function() { ... },
test3 = test2(test);
Copia codice
(function(foo, bar) { ... })(1, 2);
⤽
Copia codice
// antico
if (type == 'foo' || type == 'bar') { ... }
// migliore
if (/^(foo|bar)$/.test(type)) { ... }
// ricerca in oggetto letterale
if (({ foo : 1, bar : 1 })[type]) { ... }
⤽
Utilizzare il codice sorgente della libreria come se fosse la sua documentazione – salva il link http://bit.ly/jqsource come marcatore per usarlo come riferimento.
Ancora nessun commento