Performance du sélecteur jQuery
-
05-07-2019 - |
Question
Les performances varient considérablement en fonction de la manière dont j'exprime mes sélecteurs. Par exemple, regardez ces 2 sélecteurs, qui sélectionnent exactement les mêmes éléments:
A) someTableRow.find("td.someColumnClass").find("span.editMode").find("input")
B) someTableRow.find("td.someColumnClass span.editMode input")
Je m'attendrais à ce que B) soit plus rapide puisqu'il n'y a qu'un seul appel, mais en fait, je constate que A) s'exécute environ 8 fois plus rapidement. Je ne sais pas pourquoi, quelqu'un a une idée? Merci
La solution
En supposant que vous utilisiez au moins jQuery 1.3 (c’est-à-dire avec l’ajout de Sizzle), les performances observées sont dues au changement de parcours du DOM. De ici :
Jusqu’à jQuery 1.2.6 inclus, la Le moteur de sélection fonctionnait de manière "descendante". (ou "de gauche à droite") manière. jQuery 1.3.x ( Sizzle , que jQuery intègre) introduit un "bottom up". ; (ou "de droite à gauche") approche de la requête les DOM.
Dans votre deuxième exemple ( " td.someColumnClass span.editMode input "
), Sizzle le fait effectivement:
- récupère tous les éléments
input
danssomeTableRow
- pour chaque élément
input
trouvé, parcourez son arbre ancêtre pour les élémentsspan
avecclass = " editMode & <; code>. Supprimer les éléments
input
ne possédant pas ces ancêtres - pour chaque élément
span.editMode
trouvé, parcourez son arbre ancêtre pour les élémentstd
avecclass = "someColumnClass &
". Supprimer les élémentsinput
ne possédant pas ces ancêtres
Dans votre premier exemple, vous qualifiez explicitement chaque étape avec chaque appel de find ()
, définissez un contexte et parcourez bas à partir de là. Vous appliquez les règles " descendantes " approche. Cela équivaut à passer dans un contexte à chaque étape, généralement considéré comme un accélérateur de performances :
$('input', $('span.editMode', $('td.someColumnClass', someTableRow)))
Autres conseils
Parce que vous réduisez le contexte de la recherche.
Dans le cas B, il doit rechercher dans chaque élément du DOM pour voir s'il répond aux critères.
Dans le cas A, il peut rapidement décider d'ignorer tout ce qui n'est pas "td.someColumnClass", puis peut utiliser ce sous-ensemble du DOM et ignorer tout ce qui ne se trouve pas dans "span.editMode". Il contient donc un ensemble d’éléments beaucoup plus réduit dans lequel rechercher des "entrées" maintenant.
A correspond à plus d'appels, mais plus simple. B est un appel, mais plus complexe. Dans ce cas, la complexité de l'appel pèse beaucoup plus que le nombre d'appels.
D'après mon expérience, JQuery gère les sélecteurs différemment de CSS.
Réduire le contexte à la recherche est la clé, comme l'a souligné Josh.
Je trouve l'utilisation des deux sélecteurs de paramètres très rapide
Comment cela se compare-t-il en termes de vitesse?
Vous n’avez pas besoin de tous les vars ici, c’est juste pour préciser ce que je fais.
var columnClasses = $('.someColumnClass');
var tableCell = $('td', columnclasses);
var editMode = $('.editmode', tableCell);
var spanInside = $('span', editMode);
var inputFinally = $('input', spanInside);
gentillesse,
Dan
J'ai moi-même effectué des recherches sur jQuery Selector Performance. Un gros problème sont les recherches par nom de classe sur Internet Explorer. IE ne prend pas en charge getElementsByClassName. Par conséquent, jQuery et d’autres frameworks " reimplement " en JavaScript en parcourant tous les éléments du DOM. Consultez le blog d'analyse suivant sur Performances de jQuery Selector
Vous trouverez ici un article très intéressant sur les performances des sélecteurs: http: // blogs .atlassian.com / developer / 2009/08 / jquery_bondage.html
Dans celui-ci, l'auteur affiche un " bind " Extension jQuery indiquant combien de fois la fonction est évaluée.