Come madrelingua inglese, le nostre menti sono orientate verso l'interpretazione di dati e testo da sinistra a destra. Tuttavia, come risulta, molti dei moderni motori di selezione JavaScript (jQuery, YUI 3, NWMatcher) e il nativo querySelectorAll
, parsing stringhe di selettore da destra a sinistra.
È importante notare che, il più delle volte, non è necessario preoccuparsi troppo delle prestazioni del selettore, a patto che i selettori non siano odiosi. Il Sizzle di jQuery è incredibilmente veloce e accomodante.
Si consideri il seguente selettore:
$ ('. box p');
Anche se alcuni motori di selezione generalmente più vecchi interrogheranno prima il DOM per l'elemento con a classe
di scatola
, e poi passare a trovare qualsiasi p
tag che sono bambini, jQuery funziona al contrario. Inizia interrogando il DOM per tutti tag di paragrafo sulla pagina, e quindi funziona fino in fondo i nodi padre e cerca .scatola
.
Possiamo usare l'eccellente sito web JsPerf.com per testare questo.
// Il markup// The Test // 1. $ ('# box p'); // 2. $ ('# box'). Find ('p');Ciao
L'immagine sopra mostra che l'uso trova()
o bambini()
è più veloce del 20-30%, a seconda del browser.
La libreria jQuery ha un'ottimizzazione che determinerà immediatamente se un file id
è stato passato all'oggetto jQuery ( $ ( '# Box')
). In questo caso, non è necessario utilizzare Sizzle; invece, passa rapidamente il selettore a getElementById
. E, naturalmente, se il browser è abbastanza moderno, querySelectorAll
sostituirà Sizzle.
D'altra parte, con $ ('# box p')
, jQuery deve analizzare questa stringa con l'API Sizzle, che richiederà un po 'più tempo (sebbene Sizzle abbia un'ottimizzazione per i selettori che iniziano con un id
). Questo è esattamente il motivo per cui è anche leggermente più veloce fare cose del genere $ ('. Elems'). Prima ()
al di sopra di $ ( 'Elems:. Primo')
. L'ultimo selettore dovrà essere analizzato.
Esaminiamo un altro esempio:
$ ('# contenitore>: disabilitato');
Questo selettore sembra appropriato. Trova tutti gli input disabilitati (o in realtà, gli elementi) all'interno #contenitore
. Tuttavia, come abbiamo imparato, jQuery e il nativo querySelectorAll
lavoro da destra a sinistra. Ciò significa che jQuery prenderà letteralmente ogni elemento nel DOM e determinerà se è il suo Disabilitato
l'attributo è impostato su true. Si noti che non esiste alcun pre-filtro per trovare prima tutti gli input sulla pagina. Invece, ogni elemento nel DOM verrà interrogato.
// Dalla sorgente jQuery disabilitata: function (elem) return elem.disabled === true;
Una volta che è stata compilata una raccolta, essa percorre la catena fino al genitore e determina se lo è #contenitore
. Certamente, questo non è efficace e, anche se è vero che forse troppa attenzione nella comunità viene pagata per le prestazioni dei selettori, dovremmo comunque sforzarci di non scrivere selettori eccessivamente intensi, quando possibile.
Puoi migliorare un po 'questo selettore facendo:
// Better $ ('# container> input: disabled');
Questo codice limiterà la query a tutti gli input sulla pagina prima (anziché a ogni elemento). Ancora meglio, però, possiamo ancora usare il trova
o bambini
metodo.
$ ( '# Container') i bambini ( 'ingresso: disabilitato');.
Per me è importante ribadire che onestamente non devi preoccuparti troppo delle prestazioni del selettore. Ci sono molte ottimizzazioni in jQuery che ti aiuteranno. In genere è meglio concentrarsi su elementi di ticket più grandi, come l'organizzazione e la struttura del codice.
Ad esempio, se Sizzle trova un selettore come $ ('# box p')
, è vero che funziona da destra a sinistra, ma c'è anche un'ottica di regex veloce che determinerà prima se la prima sezione del selettore è un id
. Se è così, lo userà come contesto, durante la ricerca dei tag di paragrafo.
Tuttavia, è sempre utile sapere cosa succede dietro le quinte, almeno a un livello molto basso.