2014-09-07 65 views
6

Tutti sanno cosa selettori DOM come document.getElementByID(...) e document.querySelector(...) fanno e come lo si può utilizzare con le classi, gli attributi, id e così via.Come funziona querySelector sotto il cofano?

Ma non sono riuscito a trovare come funziona sotto il cofano (posso trovare perf test comparisons ma sono interessato alla teoria). So che la pagina html viene caricata, analizzata dal browser e viene costruito l'albero DOM. Ma come ognuno dei selettori attraversa l'albero DOM per trovare gli elementi.

ho preso uno sguardo a un spec for parsing algorithm e leggere davvero bello explanation how Browsers work, ma anche dà spiegazione eccellente di HTML, parsing CSS e rendendo il flusso non dà spiegazione di come ciascuno di questi selettori attraversa questo albero di trovare gli elementi.

presumo che, al fine di trovare qualcosa di simile .black o span ha bisogno di attraversare tutto l'albero, ma per trovare #id può essere attraversando qualche struttura dati aggiuntivi e rendendo così molto più veloce. Si prega di non scrivere le vostre ipotesi, sto cercando conoscenze concrete con backup alle specifiche o all'implementazione in alcuni browser.

+0

penso che questo sarebbe meglio chiesto a http://programmers.stackexchange.com – spender

+7

Questo è un dettaglio di implementazione, e possono variare da quale motore che si sta utilizzando. Dovrai leggere il codice sorgente di varie implementazioni se vuoi sapere. Vedi http://en.wikipedia.org/wiki/List_of_ECMAScript_engines come punto di partenza. – slashingweapon

+0

@slashingweapon Non lo penso davvero. Questa è una funzionalità piuttosto semplice e molto probabilmente verrà implementata in modo simile nei principali browser. –

risposta

6

L'ispezione di Firefox's source e la lettura di the related documentation consentono di ottenere alcune informazioni iniziali.
Una volta che il documento viene recuperata, è passato al parser (vedi: /mozilla/parser/html/) che masticare attraverso il documento e generare un albero di contenuti. Le parti centrali del parser sono scritti in Java (/mozilla/parser/html/javasrc/) e poi tradotti in C++ per la costruzione, in modo da essere pronti ad avere un buon tempo quando si desidera leggere il resto della fonte.

Guardando alla fonte del parser (/mozilla/parser/html/javasrc/TreeBuilder.java), vale a dire un estratto dalla funzione startTag:

1579   if (errorHandler != null) { 
1580    // ID uniqueness 
1581    @IdType String id = attributes.getId(); 
1582    if (id != null) { 
1583     LocatorImpl oldLoc = idLocations.get(id); 
1584     if (oldLoc != null) { 
1585      err("Duplicate ID \u201C" + id + "\u201D."); 
1586      errorHandler.warning(new SAXParseException(
1587        "The first occurrence of ID \u201C" + id 
1588        + "\u201D was here.", oldLoc)); 
1589     } else { 
1590      idLocations.put(id, new LocatorImpl(tokenizer)); 
1591     } 
1592    } 
1593   } 

Passando attenzione alla linea 1590 e il tenendo presente che in precedenza nello stesso file che abbiamo:

459  private final Map<String, LocatorImpl> idLocations = new HashMap<String, LocatorImpl>(); 

possiamo vedere che gli iD dei nodi sono tenuti in una mappa di hash semplice. Guardare come vengono elaborate le classi è un esercizio lasciato al lettore.

diversi metodi DOM, ad esempio document.getElementByID(...), sono collegati a questo hash mappa tramite il codice di colla e una pletora di gerarchia di oggetti, vedere "How is the web-exposed DOM implemented?" on ask.mozilla.org.

+2

Ottima risposta !! –