views:

77

answers:

5

Are selectors or functions faster in jQuery? Example:

$('#something div.else'); // find multiple divs with class .else

or

$('#something').children('div.else');

I'm trying my best to optimize a page with hundreds of returned elements that seems to hang on a certain crappy computer here in the office (that must use Internet Explorer ::shudder::).

+1  A: 

i recommended to read this article its help me alot :

http://www.tvidesign.co.uk/blog/improve-your-jquery-25-excellent-tips.aspx#

http://www.componenthouse.com/article-19

Haim Evgi
+1  A: 

Well in this case, the second's faster, but, they're not equivalent. The first finds any descendant div.else, the other finds only direct children that are div.else.

It depends on your DOM as to which is faster, the equivalent of the second would be this:

$('#something > div.else');

This uses the child selector. They should be very, very close, and in any case, I doubt a selector descending from an ID is your problem area, I think you'll find the vast majority of your time in JS is spent elsewhere.

For diagnosing speed issues, get a profiler, for IE specifically there's a fantastic free one called dynaTrace AJAX Edition. Grab it, follow the short tutorials on their site...you'll find where your pain areas in IE are pretty quickly.

Nick Craver
jQuery will translate such a call into `$('#something').find('div.else')`.
jAndy
@jAndy - No, it won't. Sizzle != jQuery they are separate, it [uses Sizzle](http://github.com/jquery/jquery/blob/master/src/sizzle-jquery.js). The *effect* is the same, but it doesn't make that call. If you're meaning it's equivalent...well, again no, `.children() != .find()`.
Nick Craver
@Nick: well, I just expressed myself wrong. Sizzle will detect if the first thing within the selector string is an id, and then sizzle converts it into the `find` statement. But anyway, its in the jQuery source, so.. I never stated `.children() === .find()` anyways
jAndy
@jAndy - Fair enough, though I'm *really* confused as to what "such a call" means if you weren't referring to my answer or the question...because neither have any code that get translated that way.
Nick Craver
@Nick: indeed that was confusing, should be `Sizzle will optimize $('#something div.else') into $('#something').find('div.else)`.
jAndy
A: 

Although I haven't checked with the jQuery code, I think the difference should be negligable between your two examples - although the first one should run a little faster.

The problem with old IE versions is that they do not support a native way to fetch items based on class names. In this case, jQuery has to execute a regulra expression on each class attribute of each element contained.

If it is possible in your case, you might gain quite a lot performance when being able to select on an unusual tagname:

$("#container blockquote.else")

and ideally,leave away the class name.

EDIT: just saw the answer from Nick and he's right, the scond one only has to check the direct children. The equivalent first one would be:

$("#container > div.else")
Steffen Müller
A: 

In your specific example, your first example of

$('#something div.else');

gets optimized through Sizzle (which is delivered within the jQuery lib) into

$('#something').find('div.else');

without that optimization, it would be slower, since the selector engine sizzle does work from right to left. So, it would match all divs with the class else and would then check which of those has #something as parent.

edit

The Sizzle optimazation is slower anyway, since it took a while until that task is completed and some functions are called on the way

In general, using jQuery functions is a lot faster. For instance jQuerys .eq() function will use an array slice to reduce a wrappet set of jQuery objects, whereas :eq() selector will invoke sizzle.

If in your example, div.else elements are direct children of #something, .children() will beat .find() since .find() will also lookup all descendants (and their childs).

jAndy
jQuery does not make this optimization, it passes the selector to sizzle. `$('#something div.else');` gets turned into `$(document).find('#something div.else');`, not `$('#something').find('div.else');`. jQuery doesn't tinker with selectors like this.
Nick Craver
@Nick: well, I just expressed myself wrong. Sizzle will detect if the first thing within the selector string is an id, and then sizzle converts it into the `find` statement. But anyway, its in the jQuery source, so..
jAndy
@jAndy - It's not "in the source", it's *built* with jQuery, but Sizzle itself is a separate project, and included in a few libraries, you can find its source here: http://github.com/jeresig/sizzle/blob/master/sizzle.js As for the convert, it doesn't matter what the first of the string is, any space split (not including a special selector, e.g. `>`) is a `.find()`: http://github.com/jeresig/sizzle/blob/master/sizzle.js#L88
Nick Craver
@Nick: hairsplitting ?
jAndy
@jAndy - When you're talking about performance and optimization? **Absolutely**, where things happen matter a great deal in this context. Normally it wouldn't matter a bit because the difference is so infinitesimal, but when you're talking about *performance*, it relates directly to the issue.
Nick Craver
A: 

If I understand correctly you need the fastest way to get #something div.else in IE6. Since jQuery uses Sizzle, the way it will find that is first find all div's, then filter by the ones with the else class, and has an ancestor with the #something id.

Your second example will be faster if it contains few children, slower if it contains many.

A suggestion you could try would be to use another tag type instead of div, one that isn't used in your page, say blockquote. Just reset it's styles with css so it looks like a normal div, then change your selector to #something blockquote.else which should be tons faster.

manixrock