Por esta respuesta, me refiero a querySelector, y querySelectorAllcomo querySelector * y para getElementById, getElementsByClassName, getElementsByTagName, y getElementsByNamecomo getElement *.
Principales diferencias
- querySelector * es más flexible, ya que puede pasarle cualquier selector CSS3, no solo los simples para identificación, etiqueta o clase.
- El rendimiento de querySelector cambia con el tamaño del DOM en el que se invoca. * Para ser precisos, las llamadas querySelector * se ejecutan en tiempo O (n) y las llamadas getElement * se ejecutan en tiempo O (1), donde n es el número total de todos los elementos secundarios del elemento o documento en el que se invoca. Este hecho parece ser el menos conocido, así que lo estoy resaltando.
- Las llamadas getElement * devuelven referencias directas al DOM, mientras que querySelector * internamente hace copias de los elementos seleccionados antes de devolverles referencias. Estos se denominan elementos "en vivo" y "estáticos". Esto NO está estrictamente relacionado con los tipos que devuelven. No hay forma de saber si un elemento está vivo o estático programáticamente, ya que depende de si el elemento se copió en algún momento y no es una propiedad intrínseca de los datos. Los cambios en los elementos activos se aplican de inmediato: cambiar un elemento activo lo cambia directamente en el DOM y, por lo tanto, la siguiente línea de JS puede ver ese cambio y se propaga a cualquier otro elemento activo que haga referencia a ese elemento inmediatamente. Los cambios en los elementos estáticos solo se vuelven a escribir en el DOM después de que se ejecuta la secuencia de comandos actual.
- Los tipos de devolución de estas llamadas varían.
querySelectory getElementByIdambos devuelven un solo elemento. querySelectorAlly getElementsByNameambos devuelven NodeLists, que son funciones más nuevas que se agregaron después de que HTMLCollection pasara de moda. Los más antiguos getElementsByClassNamey los getElementsByTagNamedos devuelven colecciones HTMLC. Nuevamente, esto es esencialmente irrelevante para saber si los elementos son vivos o estáticos.
Estos conceptos se resumen en la siguiente tabla.
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)
Detalles, consejos y ejemplos
Las colecciones HTMLC no son tan similares a una matriz como NodeLists y no admiten .forEach (). Creo que el operador de propagación es útil para solucionar esto:
[...document.getElementsByClassName("someClass")].forEach()
Cada elemento, y el global document, tienen acceso a todas estas funciones, excepto para getElementByIdy getElementsByName, que solo se implementan en document.
El encadenamiento de llamadas getElement * en lugar de usar querySelector * mejorará el rendimiento, especialmente en DOM muy grandes. Incluso en DOM pequeños y / o con cadenas muy largas, generalmente es más rápido. Sin embargo, a menos que sepa que necesita el rendimiento, se debe preferir la legibilidad de querySelector *. querySelectorAlla menudo es más difícil de reescribir, porque debe seleccionar elementos de NodeList o HTMLCollection en cada paso. Por ejemplo, el siguiente código no funciona:
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`.
Dado que todos los elementos tienen acceso a las consultas querySelector * y getElement *, puede hacer cadenas utilizando ambas llamadas, lo que puede ser útil si desea un aumento de rendimiento, pero no puede evitar un querySelector que no se puede escribir en términos de las llamadas getElement * .
Aunque generalmente es fácil saber si un selector se puede escribir usando solo llamadas getElement *, hay un caso que puede no ser obvio:
document.querySelectorAll(".class1.class2")
puede reescribirse como
document.getElementsByClassName("class1 class2")
El uso de getElement * en un elemento estático obtenido con querySelector * dará como resultado un elemento que está activo con respecto al subconjunto estático del DOM copiado por querySelector, pero no con respecto al documento completo DOM ... aquí es donde lo simple La interpretación en vivo / estática de los elementos comienza a desmoronarse. Probablemente debería evitar situaciones en las que deba preocuparse por esto, pero si lo hace, recuerde que querySelector * llama a los elementos de copia que encuentran antes de devolverles referencias, pero getElement * llama a buscar referencias directas sin copiar.
Ninguna API especifica qué elemento debe seleccionarse primero si hay varias coincidencias.
Debido a que querySelector * itera a través del DOM hasta que encuentra una coincidencia (ver Diferencia principal # 2), lo anterior también implica que no puede confiar en la posición de un elemento que está buscando en el DOM para garantizar que se encuentre rápidamente: el el navegador puede iterar a través del DOM hacia atrás, hacia adelante, primero en profundidad, primero en ancho o de otra manera. getElement * seguirá encontrando elementos en aproximadamente la misma cantidad de tiempo, independientemente de su ubicación.