L'arrivo di jQuery ha reso il processo di scrittura in JavaScript estremamente semplice. Tuttavia, noterai che apportare piccole modifiche al codice migliora sensibilmente la leggibilità e / o le prestazioni. Ecco alcuni suggerimenti per iniziare a ottimizzare il tuo codice.
Avremo bisogno di una solida piattaforma per condurre i nostri test. Ecco il codice HTML per la pagina di test in cui eseguiremo tutti i nostri test:
Testare i miglioramenti delle prestazioni - Siddharth / NetTuts+ Qualche testo qui
- Oh, ciao lì!
Non c'è niente di speciale qui; solo un gruppo di elementi che possiamo scegliere come target e testare. Stiamo usando Firebug per registrare i tempi qui. profilo inizia il processo, e profileEnd lo interrompe e prende nota di quanto tempo ha impiegato l'attività. Di solito uso il metodo del profilo principale di Firebug, ma per i nostri scopi subdoli, questo sarà sufficiente.
Come spesso accade, servirai un singolo file di script contenente il tuo codice su tutte le pagine del tuo sito. Questo è solitamente un codice che spesso esegue azioni su elementi inesistenti nella pagina corrente. Sebbene jQuery gestisca problemi come questi con grazia, questo non significa che puoi semplicemente ignorare qualsiasi problema. Infatti, se chiami i metodi di jQuery su una raccolta vuota, non verranno eseguiti.
Come best practice, esegui solo il codice che è applicabile alla pagina attualmente caricata, invece di raggruppare tutto il tuo codice in un unico controllo pronto per il documento e servirlo al client.
Diamo un'occhiata al primo scenario:
console.profile (); var ele = $ ("# somethingThatisNotHere"); ele.text ("Some text"). slideUp (300) .addClass ("editing"); $ ( "# MainItem"); console.profileEnd (); // Un altro codice terrificante più impressionante e macabro qui..
Firebug's sputa il seguente risultato:
Questa volta, controlliamo se l'elemento che stiamo cercando di eseguire azioni esiste prima di farlo.
console.profile (); var ele = $ ("# somethingThatisNotHere"); if (ele [0]) ele.text ("Some text"). slideUp (300) .addClass ("editing"); $ ("# mainItem"); console.profileEnd (); // Un altro codice terrificante più impressionante e macabro qui..
E i risultati:
Vedere? È piuttosto semplice, al punto e ottiene il lavoro fatto. Si noti che non è necessario verificare se un elemento esiste per ogni singolo bit del codice. Nella tua pagina noterai che alcune parti più grandi generalmente beneficiano di questo metodo. Usa il tuo giudizio qui.
Prova a utilizzare un ID anziché passare una classe.
Questo è un argomento importante, quindi lo terrò il più conciso possibile. Per prima cosa, quando passi nei selettori, prova ad usare un ID invece di passare una classe. jQuery usa direttamente il nativo getElementById metodo per trovare un elemento per ID mentre nel caso di una classe deve fare del voodoo interno per acquisirlo, almeno nei browser più vecchi.
Vedremo i diversi selettori che puoi utilizzare per scegliere come target il secondo Li elemento. Verificheremo ognuno di essi e come modificano le prestazioni.
Il primo metodo, il più semplice, sarà quello di bersagliarlo chiaramente usando il selezionato classe. Vediamo cosa restituisce il profilo di Firebug.
console.profile (); $ ( "Selezionato."); console.profileEnd ();
E il risultato: 0,308 ms. Successivamente, prefiggiamo il nome di un tag per restringerlo. In questo modo, possiamo restringere la nostra ricerca selezionando innanzitutto solo gli elementi DOM selezionati, con document.getElementsByTagName.
console.profile (); $ ( "Li.selected"); console.profileEnd ();
E il risultato: 0,291 ms. Circa 0,02 ms rasati. Questo è trascurabile a causa del fatto che stiamo testando su Firefox; tuttavia, va notato che questo aumento delle prestazioni sarà notevolmente più alto nei browser più vecchi, come Internet Explorer 6.
Successivamente, scendiamo dall'ID dell'elemento genitore.
console.profile (); $ ("# someList .selected"); console.profileEnd ();
E il risultato: 0,283 ms. Proviamo ad essere un po 'più specifici. Specifichiamo anche il tipo di elemento oltre all'ID dell'antenato.
console.profile (); $ ("# someList li.selected"); console.profileEnd ();
E il risultato: 0,275 ms. Un'altra piccola parte si è rasata. Infine, miriamo direttamente a utilizzare un ID a.
console.profile (); $ ( "# MainItem"); console.profileEnd ();
E il risultato: 0,165 ms. Impressionante! Questo ti mostra davvero quanto è più veloce eseguire i metodi nativi. Nota che mentre i browser moderni possono trarre vantaggio da cose come getElementsByClassName, i browser più vecchi non possono - con prestazioni molto più lente. Considera sempre questo durante la codifica.
Sizzle, il motore di selezione utilizzato da jQuery - costruito da John Resig - analizza i selettori da destra a sinistra, il che solleva alcune catene di analisi inaspettate.
Considera questo selettore:
$ ("# someList .selected");
Quando Sizzle incontra un tale selettore, prima costruisce la struttura DOM, usando il selettore come root, scarta elementi che non hanno la classe richiesta e, per ogni elemento con la classe, controlla se il suo genitore ha un ID di someList.
Per tener conto di ciò, assicurati che la parte più corretta del tuo selettore sia il più specifica possibile. Ad esempio, specificando li.selected invece di .selezionato, hai ridotto il numero di nodi che deve controllare. Questo è il motivo per cui le prestazioni sono saltate nella sezione precedente. Aggiungendo ulteriori vincoli, si riduce efficacemente il numero di nodi che deve controllare.
Per ottimizzare meglio il modo in cui gli elementi vengono ottenuti, è necessario esaminare l'aggiunta di un contesto per ogni richiesta.
var someList = $ ('# someList') [0]; $ (". selected", someList);
Aggiungendo un contesto, il modo in cui l'elemento viene cercato cambia completamente. Ora, l'elemento che fornisce il contesto - someList nel nostro caso - viene prima cercato e, una volta ottenuto, gli elementi figlio che non hanno la classe richiesta vengono rimossi.
Tieni presente che in genere è consigliabile trasferire un elemento DOM come contesto del selettore jQuery. L'utilizzo di un contesto è molto utile quando è memorizzato in alcune variabili. Altrimenti, puoi semplificare il processo e usare find () - che jQuery, a sua volta, fa sotto il cofano.
$ ( '# SomeList') trovare ( 'selezionato..');
Mi piacerebbe dire che l'aumento delle prestazioni sarà chiaramente definito, ma non posso. Ho eseguito test su un certo numero di browser e se la performance dell'approccio con scope supera quella della versione vanilla dipende da una serie di fattori tra cui se il browser supporta metodi specifici.
Quando sfogli il codice di qualcun altro, troverai spesso.
// Altro codice $ (elemento) .doSomething (); // Più codice $ (elemento) .doSomethingElse (); // Ancora più codice $ (elemento) .doMoreofSomethingElse ();
Per favore, non farlo. Mai. Lo sviluppatore sta istanziando questo "elemento" più e più volte. Questo è uno spreco.
Vediamo quanto tempo impiega questo orrendo codice per funzionare.
console.profile (); $ ( "# MainItem") nascondere ().; $ ( "# MainItem") val ( "Ciao").; $ ("# mainItem"). html ("Oh, hey there!"); $ ( "# MainItem") show ().; console.profileEnd ();
Se il codice è strutturato come sopra, uno dopo l'altro, puoi usare il concatenamento in questo modo:
console.profile (); $ ("# mainItem"). hide (). val ("Hello"). html ("Oh, hey there!"). show (); console.profileEnd ();
Concatenando, l'elemento inizialmente passato viene acquisito e un riferimento viene passato a ciascuna chiamata successiva riducendo il tempo di esecuzione. Altrimenti viene creato un nuovo oggetto jQuery ogni volta.
Ma se diversamente da sopra, le sezioni che fanno riferimento all'elemento non sono simultanee, dovrai mettere in cache l'elemento e poi fare tutte le stesse operazioni di prima.
console.profile (); var elem = $ ("# mainItem"); elem.hide (); // Alcuni codice elem.val ("Ciao"); // Altro codice elem.html ("Oh, hey there!"); // Ancora più codice elem.show (); console.profileEnd ();
Come è evidente dai risultati, il caching o il concatenamento diminuisce considerevolmente il tempo di esecuzione.
Suggerire una manipolazione DOM non tradizionale nel mio articolo precedente ha suscitato un piccolo disturbo da alcune persone prima di mostrare che l'aumento delle prestazioni è davvero valsa la pena. Lo testeremo ora da soli.
Per il test, creeremo 50 Li elementi e aggiungerli all'elenco corrente e determinare il tempo necessario.
Esamineremo prima il metodo normale e inefficiente. Stiamo praticamente aggiungendo l'elemento all'elenco ogni volta che viene eseguito il ciclo.
console.profile (); var list = $ ("# someList"); per (var i = 0; i<50; i++) list.append('
Vediamo come è andata, dobbiamo?
Ora seguiremo un percorso leggermente diverso. In pratica aggiungeremo la stringa HTML richiesta a una variabile, quindi restituiremo il DOM una sola volta.
console.profile (); var list = $ ("# someList"); var items = ""; per (var i = 0; i<50; i++) items += '
Come previsto, il tempo impiegato è diminuito in modo significativo.
Se stai usando jQuery come sostituto di getElementById, ma non usi mai nessuno dei suoi metodi, allora lo stai facendo male.
Se desideri fare ulteriori passi, chiediti se hai davvero bisogno di creare un nuovo oggetto jQuery tutto allo scopo di bersagliare qualche elemento? Se stai usando jQuery come sostituto di document.getElementById, ma non usi mai nessuno dei suoi metodi, allora stai sbagliando. In questo caso, possiamo farla franca con JS non elaborato.
console.profile (); var list = document.getElementById ('someList'); var items = "; for (var i = 0; i<50; i++) items += '
Noterai che la differenza nel tempo di esecuzione tra il codice ottimizzato e quello non ottimizzato è nella frazione di un intervallo di millisecondi. Questo perché il nostro documento di test è molto piccolo con un numero incredibilmente piccolo di nodi. Una volta che inizi a lavorare con siti a livello di produzione con qualche migliaio di nodi al suo interno, questo verrà davvero sommato.
Si noti inoltre che nella maggior parte di questi test sto semplicemente accedendo agli elementi. Quando inizi ad applicare funzioni appropriate a loro, il delta nel tempo di esecuzione aumenterà.
Capisco anche che questo non è il metodo più scientifico per testare le prestazioni, tuttavia, per avere un'idea generale di quanto ognuna di queste modifiche influisce sulla performance, penso che sia sufficientemente adeguata.
Infine, nella maggior parte delle tue app Web, la velocità di connessione e il tempo di risposta del server Web in questione giocheranno un ruolo più importante nelle prestazioni della tua app rispetto alle modifiche apportate al codice. Ciononostante, si tratta di informazioni importanti che ti aiuteranno ad andare avanti quando stai cercando di ottenere il maggior numero possibile di prestazioni dal tuo codice.
E abbiamo finito. Alcuni punti da tenere a mente quando stai cercando di ottimizzare il tuo codice; questo non è l'elenco completo di modifiche, ovviamente, ei punti potrebbero non essere necessariamente applicabili a tutte le situazioni. Ad ogni modo, osserverò attentamente i commenti per leggere ciò che hai da dire sull'argomento. Qualche errore che vedi qui? Mandami una riga qui sotto.
Domande? Belle cose da dire? Critiche? Colpisci la sezione dei commenti e lasciami un commento. Buona programmazione!