Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery selector performance

I'm having huge variations in performance depending on how I express my selectors. For example, look at these 2 selectors, which select exactly the same elements:

A) someTableRow.find("td.someColumnClass").find("span.editMode").find("input")
B) someTableRow.find("td.someColumnClass span.editMode input")

I would expect to B) to be faster as there is only 1 call, but in fact I'm finding A) executes around 8 times faster. I have no idea why, anyone have any insight? Thanks

like image 358
JonoW Avatar asked Sep 11 '09 14:09

JonoW


People also ask

Which is the fastest selector in jQuery?

ID Selector: The jQuery #id selector selects the element on the basis of the ID attribute of the HTML tag. This selector is basically used when we have to work on a single element because an ID should be unique within a web page.

Is the universal selector slow?

In modern browsers the performance impact is negligible, provided you don't apply slow-effects to every element (eg. box-shadow, z-axis rotation). The myth that the universal-selector is slow is a hangover from ten years ago when it was slow. Save this answer.

Which selector is faster in JavaScript?

ID and Element selector are the fastest selectors in jQuery.


1 Answers

Presuming you are using at least jQuery 1.3 (i.e. with the addition of Sizzle), the performance you are seeing is due to the change in which the DOM is traversed. From here:

Up to and including jQuery 1.2.6 the selector engine worked in a "top down" (or "left to right") manner. jQuery 1.3.x (ie, Sizzle, which jQuery embeds) introduced a "bottom up" (or "right to left") approach to querying the DOM.

In your second example ("td.someColumnClass span.editMode input"), Sizzle effectively does this:

  1. get all input elements inside someTableRow
  2. for each input element found, traverse its ancestor tree for span elements with class="editMode". Remove input elements that don't have these ancestors
  3. for each span.editMode element found, traverse its ancestor tree for td elements with class="someColumnClass". Remove input elements that don't have these ancestors

In your first example however, your are qualifying each step explicitly with each call to find(), defining a context and traversing down from there. You are enforcing the "top-down" approach. It is equivalent to passing in a context at each step, which is generally considered a performance booster:

$('input', $('span.editMode', $('td.someColumnClass', someTableRow)))
like image 182
Crescent Fresh Avatar answered Nov 15 '22 03:11

Crescent Fresh