javascript - clase - jquery selector
¿Cómo se evalúa el selector jQuery $(''# foo a'')? (7)
Como ejemplo del código jQuery ( https://coderwall.com/p/7uchvg ), leo que la expresión $(''#foo a'');
se comporta así:
Encuentre cada
a
en la página y luego filtrea
#foo
interno.
Y no parece eficiente.
¿Es eso correcto? Y si es así, ¿cómo deberíamos hacerlo de una mejor manera?
¿Cómo deberíamos hacer eso de una mejor manera?
Use el parámetro de contexto de jQuery.
$(''a'', ''#foo'');
Ahora jQuery buscará todos los anclajes dentro del contexto del elemento con id: foo.
En su consulta, el contexto está predeterminado para documentar cuando se omite:
$(''#foo a''); == $(''#foo a'', document);
En este caso, su consulta no es eficiente.
Puede echar un vistazo a este artículo .
En lugar de filtrar con elementos dentro de #foo
, simplemente adjunte una clase a a
elemento y obtenga elementos con una clase como $("a.class");
. Esto sería más eficiente.
Eso es correcto: Sizzle (motor selector de jQuery) se comporta de la misma manera que los selectores de CSS . Los selectores CSS y Sizzle se evalúan de derecha a izquierda , por lo que #foo a
encontrará todos los nodos, luego los filtrará por nodos que descienden de #foo
.
Mejore esto al asegurar que sus selectores de hojas tengan una alta especificidad, generalmente dándoles una clase o ID.
Este ejemplo recuperará los elementos de todas las anclas a
en un elemento llamado foo
, para encontrar cada una en la página y luego filtrar una dentro de #foo como quieras, debes seleccionar a #foo
$("a #foo");
esto recuperará todos los elementos foo
dentro de a
elemento.
Otro más "pruébalo por ti mismo":
- jsperf para varios selectores en 10000 elementos
- jsperf para varios selectores en 300 elementos
- jsperf para varios selectores en un "DOM más representativo"
No parece haber mucha diferencia con un DOM "plano" (1 y 2), pero el rendimiento varía mucho más con un DOM anidado.
También tenga en cuenta que algunos de los casos de prueba no están seleccionando los elementos correctos (es decir $(''.a'')
versus $(''.a'', context)
), pero los dejé de las pruebas originales solo para comparar.
Puede usar find () para obtener un control más detallado en su orden de selector:
$(''#foo'').find(''a'');
Por supuesto, esto será más impresionante con selectores más complejos, donde puede encontrar cadenas () y filtrar ().
Para el registro $(''#foo'').find(''a'') === $(''a'',''#foo'')
[Actualizar] ok, más tarde me di cuenta de que es exactamente lo que dice tu enlace ...
El motor de selección de jQuery (Sizzle) se refactivó el año pasado, aquí encontrará explicaciones detalladas: http://www.wordsbyf.at/2011/11/23/selectors-selectoring/
Si bien es cierto que Sizzle es un motor de derecha a izquierda (que es de la misma manera que se interpreta css), no es cierto que el selector específico en su ejemplo seleccione todos los elementos de anclaje en la página y luego filtre a sus padres para coincide con el id de "foo". Sizzle realmente optimiza cualquier selector que comience con una ID y lo usa como contexto para toda la selección, en lugar de usar el documento. En otras palabras, el selector que ha elegido básicamente se traduce en:
document.getElementById("foo").getElementsByTagName("a")
Realmente, eso no es un mal selector en absoluto.
Sin embargo, dadas las otras cosas que jQuery necesita hacer (lo que incluye recorrer los elementos para fusionarlos en la instancia de jQuery), jQuery ("# foo"). Find ("a") siempre será el más rápido porque jQuery implementa un jQuery acceso directo de creación de objetos para selectores id-only, y luego realiza la búsqueda rooteada desde #foo.
En otras palabras, Sizzle no es muy diferente al hacer Sizzle("#foo a")
y Sizzle("a", document.getElementById("foo"))
, pero jQuery("#foo").find...
será más rápido debido al propio atajo de identificación de jQuery.
Por cierto, mis comentarios sobre Sizzle supone que querySelectorAll no se está utilizando. Si es así, Sizzle simplemente lo pasa a qsa, que todavía no es tan rápido como usar el atajo de identificación de jQuery.