querySelector e querySelectorAll vs getElementsByClassName e getElementById in JavaScript


165

Vorrei sapere qual è esattamente la differenza tra querySelectore querySelectorAllcontro getElementsByClassNamee getElementById?

Da questo link ho potuto constatare che querySelectorposso scrivere document.querySelector(".myclass")per ottenere elementi con classe myclasse document.querySelector("#myid")ottenere elementi con ID myid. Ma posso già farlo getElementsByClassNamee getElementById. Quale dovrebbe essere preferito?

Lavoro anche in XPage in cui l'ID viene generato dinamicamente con due punti e assomiglia a questo view:_id1:inputText1. Quindi quando scrivo document.querySelector("#view:_id1:inputText1")non funziona. Ma la scrittura document.getElementById("view:_id1:inputText1")funziona. Qualche idea sul perché?


1
querySelector viene utilizzato per eseguire query su un albero DOM HTML che può includere l'elemento html e i suoi attributi come elementi chiave per l'interrogazione ... è possibile utilizzare l'espressione regolare per ottenere questo risultato. dojo.query () fa la stessa cosa
anix

1
Non intendi document.querySelectorAll(".myclass")? L'utilizzo document.querySelector(".myclass")restituirà solo il primo elemento corrispondente.
mhatch,

Risposte:


113

Vorrei sapere qual è esattamente la differenza tra querySelector e querySelectorAll rispetto a getElementsByClassName e getElementById?

La sintassi e il supporto del browser.

querySelector è più utile quando si desidera utilizzare selettori più complessi.

ad esempio, tutti gli elementi dell'elenco discendono da un elemento membro della classe foo: .foo li

document.querySelector ("# view: _id1: inputText1") non funziona. Ma scrivere document.getElementById ("view: _id1: inputText1") funziona. Qualche idea sul perché?

Il :personaggio ha un significato speciale all'interno di un selettore. Devi scappare. (Il carattere di escape del selettore ha un significato speciale anche in una stringa JS, quindi devi scappare anche quello ).

document.querySelector("#view\\:_id1\\:inputText1")

3
Varia da browser a browser (e da versione a versione). Suppongo che quelli basati sui selettori fossero più costosi (ma non in un modo che sarà probabilmente significativo)
Quentin

1
Sostengo l'affermazione di @ janaspage. Anche il sito è inattivo oggi.
doplumi,

6
E sulla selezione della classe vedi anche jsperf.com/getelementsbyclassname-vs-queryselectorall/25 . Conclusione: si dovrebbe preferire di gran lunga javascript puro rispetto a jquery, e le funzioni specifiche getElementByIde getElementsByClassName. La selezione className può essere qualche centinaia di volte più lenta senza getElementsByClassName.
Atrahasis,

101

raccolta dalla documentazione di Mozilla:

L'interfaccia NodeSelector Questa specifica aggiunge due nuovi metodi a tutti gli oggetti che implementano le interfacce Document, DocumentFragment o Element:

querySelector

Restituisce il primo nodo Element corrispondente all'interno della sottostruttura del nodo. Se non viene trovato alcun nodo corrispondente, viene restituito null.

querySelectorAll

Restituisce un NodeList contenente tutti i nodi Element corrispondenti all'interno della sottostruttura del nodo o un NodeList vuoto se non viene trovata alcuna corrispondenza.

e

Nota: il NodeList restituito da querySelectorAll()non è attivo , il che significa che le modifiche al DOM non si riflettono nella raccolta. Ciò è diverso dagli altri metodi di query DOM che restituiscono elenchi di nodi attivi.


32
+1 per indicare la distinzione dell'elenco dei nodi live. Questa è una differenza estremamente importante da tenere presente a seconda di come si intende utilizzare i risultati.
jmbpiano,

7
"live" indica il nodo aggiunto nel runtime DOM e può funzionare su quel nodo appena aggiunto
diEcho

83

Per quanto riguarda le differenze, c'è un risultato importante nei risultati tra querySelectorAlle getElementsByClassName: il valore di ritorno è diverso. querySelectorAllrestituirà una raccolta statica, mentre getElementsByClassNamerestituisce una raccolta dal vivo. Ciò potrebbe creare confusione se si memorizzano i risultati in una variabile per un uso successivo:

  • Una variabile generata con querySelectorAllconterrà gli elementi che soddisfacevano il selettore nel momento in cui è stato chiamato il metodo .
  • Una variabile generata con getElementsByClassNameconterrà gli elementi che soddisfacevano il selettore quando viene utilizzato (che potrebbe essere diverso dal momento in cui è stato chiamato il metodo).

Ad esempio, nota come anche se non hai riassegnato le variabili aux1e aux2queste contengono valori diversi dopo l'aggiornamento delle classi:

// storing all the elements with class "blue" using the two methods
var aux1 = document.querySelectorAll(".blue");
var aux2 = document.getElementsByClassName("blue");

// write the number of elements in each array (values match)
console.log("Number of elements with querySelectorAll = " + aux1.length);
console.log("Number of elements with getElementsByClassName = " + aux2.length);

// change one element's class to "blue"
document.getElementById("div1").className = "blue";

// write the number of elements in each array (values differ)
console.log("Number of elements with querySelectorAll = " + aux1.length);
console.log("Number of elements with getElementsByClassName = " + aux2.length);
.red { color:red; }
.green { color:green; }
.blue { color:blue; }
<div id="div0" class="blue">Blue</div>
<div id="div1" class="red">Red</div>
<div id="div2" class="green">Green</div>


2
Solo per citare: tutte le vecchie API DOM che restituiscono un elenco di nodi document.getElementsByName, ovvero , document.getElementsByTagNameNSo document.getElementsByTagNamemostreranno lo stesso comportamento.
RBT,

2
Alcune analisi indicano che querySelector richiede più tempo di getElementById, come qui dimlucas.com/index.php/2016/09/17/… . E se prendessimo in considerazione il tempo di accesso? Il nodo live ottenuto da getElementById richiede più tempo di quello statico da querySelector?
Eric,

1
@RBT Menzionerei che queste vecchie API DOM non restituiscono oggetti NodeList, ma restituiscono HTMLCollections.
Miscreant

@Eric document.getElementById()non restituisce un nodo attivo . È più veloce che document.querySelector('#id_here')probabilmente perché querySelectordovrà prima analizzare il selettore CSS.
Miscreant

68

Per questa risposta, mi riferisco a querySelectore querySelectorAllcome querySelector * e getElementById, getElementsByClassName, getElementsByTagName, e getElementsByNamecome getElement *.

Differenze principali

  1. querySelector * è più flessibile, poiché puoi passarlo a qualsiasi selettore CSS3, non solo a quelli semplici per ID, tag o classe.
  2. Le prestazioni di querySelector cambiano con la dimensione del DOM su cui viene invocato. * Per essere precisi, le query querySelector * vengono eseguite in O (n) time e getElement * le chiamate vengono eseguite in O (1) time, dove n è il numero totale di tutti i figli dell'elemento o del documento su cui viene invocato. Questo fatto sembra essere il meno noto, quindi lo sto audendo.
  3. Le chiamate getElement * restituiscono riferimenti diretti al DOM, mentre querySelector * esegue internamente copie degli elementi selezionati prima di restituire riferimenti a essi. Questi sono indicati come elementi "attivi" e "statici". Questo NON è strettamente correlato ai tipi che restituiscono. Non ho modo di sapere se un elemento è attivo o statico a livello di codice, in quanto dipende dal fatto che l'elemento sia stato copiato a un certo punto e non sia una proprietà intrinseca dei dati. Le modifiche agli elementi live si applicano immediatamente: la modifica di un elemento live lo modifica direttamente nel DOM, quindi la riga successiva di JS può vedere quel cambiamento e si propaga a qualsiasi altro elemento live che fa riferimento immediatamente a quell'elemento. Le modifiche agli elementi statici vengono riscritte nel DOM solo dopo l'esecuzione dello script corrente.
  4. I tipi di ritorno di queste chiamate variano. querySelectored getElementByIdentrambi restituiscono un singolo elemento. querySelectorAlled getElementsByNameentrambi restituiscono NodeLists, essendo le nuove funzioni aggiunte dopo che HTMLCollection è passato di moda. Il più vecchio getElementsByClassNameed getElementsByTagNameentrambi restituiscono HTMLCollections. Ancora una volta, questo è essenzialmente irrilevante per il fatto che gli elementi siano attivi o statici.

Questi concetti sono riassunti nella seguente tabella.

Function               | Live? | Type           | Time Complexity
querySelector          |   N   | Element        |  O(n)
querySelectorAll       |   N   | NodeList       |  O(n)
getElementById         |   Y   | Element        |  O(1)
getElementsByClassName |   Y   | HTMLCollection |  O(1)
getElementsByTagName   |   Y   | HTMLCollection |  O(1)
getElementsByName      |   Y   | NodeList       |  O(1)

Dettagli, suggerimenti ed esempi

  • Le HTMLCollections non sono simili agli array come NodeLists e non supportano .forEach (). Trovo l'operatore di spread utile per aggirare questo:

    [...document.getElementsByClassName("someClass")].forEach()

  • Ogni elemento, e il globale document, hanno accesso a tutte queste funzioni ad eccezione di getElementByIde getElementsByName, che sono implementate solo su document.

  • Concatenare le chiamate getElement * invece di utilizzare querySelector * migliorerà le prestazioni, specialmente su DOM molto grandi. Anche su piccoli DOM e / o con catene molto lunghe, è generalmente più veloce. Tuttavia, a meno che non si sappia che sono necessarie le prestazioni, è preferibile la leggibilità di querySelector *. querySelectorAllè spesso più difficile da riscrivere, perché è necessario selezionare elementi da NodeList o HTMLCollection ad ogni passaggio. Ad esempio, il seguente codice non funziona:

document.getElementsByClassName("someClass").getElementsByTagName("div")

because you can only use getElements* on single elements, not collections. For example:

`document.querySelector("#someId .someClass div")`

could be written as:

document.getElementById("someId").getElementsByClassName("someClass")[0].getElementsByTagName("div")[0]

Note the use of `[0]` to get just the first element of the collection at each step that returns a collection, resulting in one element at the end just like with `querySelector`.
  • Poiché tutti gli elementi hanno accesso a entrambe le chiamate querySelector * e getElement *, puoi creare catene usando entrambe le chiamate, il che può essere utile se vuoi un certo guadagno in termini di prestazioni, ma non puoi evitare un querySelector che non può essere scritto in termini di chiamate getElement * .

  • Sebbene sia generalmente facile capire se un selettore può essere scritto usando solo le chiamate getElement *, c'è un caso che potrebbe non essere ovvio:

    document.querySelectorAll(".class1.class2")

    può essere riscritto come

    document.getElementsByClassName("class1 class2")

  • L'uso di getElement * su un elemento statico recuperato con querySelector * comporterà un elemento attivo rispetto al sottoinsieme statico del DOM copiato da querySelector, ma non attivo rispetto al documento completo DOM ... qui è dove il semplice l'interpretazione live / statica degli elementi inizia a sfaldarsi. Probabilmente dovresti evitare le situazioni in cui devi preoccuparti di questo, ma se lo fai, ricorda che querySelector * chiama gli elementi di copia che trovano prima di restituire riferimenti a loro, ma getElement * chiama recuperare riferimenti diretti senza copiare.

  • Nessuna delle API specifica quale elemento deve essere selezionato per primo se ci sono più corrispondenze.

  • Poiché querySelector * scorre il DOM fino a quando non trova una corrispondenza (vedi la differenza principale n. 2), quanto sopra implica anche che non puoi fare affidamento sulla posizione di un elemento che stai cercando nel DOM per garantire che venga trovato rapidamente: il browser può scorrere il DOM indietro, avanti, prima in profondità, prima in larghezza o in altro modo. getElement * troverà comunque elementi all'incirca nello stesso lasso di tempo, indipendentemente dal loro posizionamento.


4
Di gran lunga la risposta più precisa su questo argomento. Dovrebbe essere votato di più.
SeaWarrior404

molto preciso dovrebbe essere messo nel tuo blog, Sasha
theking2 l'

25

Sono venuto a questa pagina puramente per scoprire il metodo migliore da utilizzare in termini di prestazioni, ovvero che è più veloce:

querySelector / querySelectorAll or getElementsByClassName

e ho trovato questo: https://jsperf.com/getelementsbyclassname-vs-queryselectorall/18

Esegue un test sui 2 esempi precedenti, oltre a mandare in test anche il selettore equivalente di jQuery. i risultati dei miei test sono stati i seguenti:

getElementsByClassName = 1,138,018 operations / sec - <<< clear winner
querySelectorAll = 39,033 operations / sec
jquery select = 381,648 operations / sec

1
Wow, questa è una differenza enorme , grazie per averlo cercato. Chiaramente ha querySelectorAllbisogno di ulteriore lavoro dietro le quinte (incluso l'analisi dell'espressione del selettore, la contabilizzazione di pseudo elementi, ecc.), Mentre getElementsByClassNameè semplicemente un attraversamento di oggetti ricorsivo.
John Weisz,

18

querySelector può essere un CSS (3) -Selector completo con ID e classi e pseudo-classi insieme in questo modo:

'#id.class:pseudo'

// or

'tag #id .class .class.class'

con getElementByClassNamete puoi semplicemente definire una classe

'class'

con getElementByIdte puoi semplicemente definire un ID

'id'

1
È :firstun selettore CSS, ora? :first-class, o :first-of-typeforse, ma pensavo :firstfosse un'aggiunta JavaScript / jQuery / Sizzle.
David dice di reintegrare Monica il

@DavidThomas Sì, è parte di CSS3. Può essere usato in questo modo: css-tricks.com/almanac/selectors/f/first-child
algoritmo

2
ma :firstè, evidentemente, no :first-child.
David dice di ripristinare Monica il

3
"Si consiglia agli autori che, sebbene sia consentito l'uso di pseudo-elementi nei selettori, non corrisponderanno a nessun elemento del documento e quindi non si tradurrebbe in alcun elemento restituito. Pertanto, si consiglia agli autori di evitare l'uso di pseudo- elementi nei selettori che vengono passati ai metodi definiti in questa specifica. " w3.org/TR/selectors-api/#grammar
rich remer

Inoltre, c'è un bug in IE (ovviamente) che provoca la restituzione dell'elemento html radice invece di un elenco di elementi vuoto quando si selezionano gli pseudo-elementi.
rich remer il

7

querySelectore querySelectorAllsono API relativamente nuove, mentre getElementByIde getElementsByClassNamesono state con noi per molto più tempo. Ciò significa che ciò che utilizzerai dipenderà principalmente dai browser che devi supportare.

Per quanto riguarda il :, ha un significato speciale, quindi devi scappare se devi usarlo come parte di un nome ID / classe.


13
Questo non è necessariamente vero. Ad esempio, querySelectorAllè disponibile in IE8, mentre getElementsByClassNamenon lo è.
DaveJ,

querySelectorAll... praticamente tutto: caniuse.com/#search=querySelectorAll
dsdsdsdsd


5

querySelectorè dell'API selettore w3c

getElementByè dell'API DOM di w3c

IMO la differenza più notevole è che il tipo restituito querySelectorAllè un elenco di nodi statici e per getElementsByesso è un elenco di nodi attivi. Pertanto il looping nella demo 2 non finisce mai perché lisè attivo e si aggiorna da solo durante ogni iterazione.

// Demo 1 correct
var ul = document.querySelectorAll('ul')[0],
    lis = ul.querySelectorAll("li");
for(var i = 0; i < lis.length ; i++){
    ul.appendChild(document.createElement("li"));
}

// Demo 2 wrong
var ul = document.getElementsByTagName('ul')[0], 
    lis = ul.getElementsByTagName("li"); 
for(var i = 0; i < lis.length ; i++){
    ul.appendChild(document.createElement("li")); 
}

4

Differenza tra "querySelector" e "querySelectorAll"

//querySelector returns single element
let listsingle = document.querySelector('li');
console.log(listsingle);


//querySelectorAll returns lit/array of elements
let list = document.querySelectorAll('li');
console.log(list);


//Note : output will be visible in Console
<ul>
<li class="test">ffff</li>
<li class="test">vvvv</li>
<li>dddd</li>
<li class="test">ddff</li>
</ul>


2

guarda questo

https://codepen.io/bagdaulet/pen/bzdKjL

getElementById più veloce di querySelector il 25%

jquery è il più lento

var q = time_my_script(function() {

    for (i = 0; i < 1000000; i++) {
         var w = document.querySelector('#ll');
    }

});

console.log('querySelector: '+q+'ms');

-3

La differenza principale tra querySelector e getlementbyID (Claassname, Tagname ecc.) È se ci sono più di un elemento che satura la condizione querySelector restituirà un solo output mentre getElementBy * restituirà tutti gli elementi.

Consideriamo un esempio per renderlo più chiaro.

 <nav id="primary" class="menu">
                            <a class="link" href="#">For Business</a>
                            <a class="link" href="#">Become an Instructor</a>
                            <a class="link" href="#">Mobile Applications</a>
                            <a class="link" href="#">Support</a>
                            <a class="link" href="#">Help</a>
   </nav> 

Di seguito il codice spiegherà la differenza

**QUERY SELECTOR**
document.querySelector('.link'); // Output : For Business (element)

document.querySelectorAll('.link'); //Out All the element with class link

**GET ELEMENT**
document.getElementsByClassName('link') // Output : will return all the element with a class "link" but whereas in query selector it will return only one element which encounters first.

Inshort se vogliamo selezionare un singolo elemento go per queryslector o se vogliamo più elementi go per getElement


1
getElementById restituisce solo un elemento, questa non è affatto una differenza tra i due.
Timofey 'Sasha' Kondrashov,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.