Performance of jQuery selector with context
I was reading this article by Brandon Aaron here, about how jquery context may help. So i thought of doing a test of my own. So this is what I did.
Created a DIV with id="context" and nested DIV with id="holder" in "#context" created earlier.
Created a nested DIVs of depth 18 and append
<div id="context"><div id="holder"></div></div>
to it resulting in 20 nested DIVsNow I tested time taken to access "#holder" via the following selectors:
a.$("#holder") // no context
b.$("#holder", "#context") // with "#context" selector string
c.$("#holder", $("#context")) // sending jquery object each time with selector "#context"
d.$("#holder", $context) // where, var $context = $("#context"). Caching jquery obj
Each of the cases where accessedX = 1000
times and start and end time difference was noted. I found that time taken for: case(a) was the least consistent 28-32msec [jquery-1.3.2] case(b)+(c) had the highest times 60-65 msec & 70-75 msec respectively case(d) had 40-50msec with 1 or 2 spiked values.
Is this type of basic check valid? You can play with the JS code here at JSBIN. [Do let me know If I开发者_StackOverflow社区 can improve this test some how]
If YES, then how does this 'context' really help? #NOTE: also replace the jquery-1.3.2 with jquery-1.4.2 in jsbin edit mode and you'll be surprised to see the numbers bump up :PContext really helps when you have a much larger DOM that you are searching through. Searching for IDs is already very fast and context doesn't really help that much in that case. Where context can really make a difference is when you are selecting by tag name or class.
Try testing like this: http://jsbin.com/aciji4/4
you can really see the timing get better for context when you bump up number of items in the DOM like this: http://jsbin.com/aciji4/6
It would make sense that it would take longer to use a context (vs. using a selector alone) since internally, the context uses the .find() method, so in essence, all you are really doing is
$('#context').find('#holder');
I mainly see it as an easier way to identify elements in events and iterators where the context changes because
$('.holder', this)
is prettier than
$(this).find('.holder')
The #ID selector relies on the browser native document.getElementById. It's going to be fast no matter what.
Try a selector like div.class[attribute=value] with and without a context. For example*, you could select the "Related" question links to the right with this selector:
// Selects anchor elements with href's beginning with /questions/
$('a[href^=/questions/]')
But, it's faster to limit how many anchor elements the selector engine has to iterate over, evaluating that relatively expensive text matching:
$('a[href^=/questions/]', '.related')
* And ignoring the obviously easier .question-hyperlink class on those links, for the sake of discussion.
For what it's worth, $context = $("#context")
is still using a jQuery object, which then has to be converted to a DOM object.
If you use $context = $("#context")[0]
you'll find that it runs just as fast as the first test.
I've taken the JSBin code and put it into a jsPerf Test
$context.find('.holder') is twice as fast as its closest competitor, $('.holder', $context) and that is a good ten times faster than any other selector being used.
In conclusion, cache your selectors and use .find() for maximum performance
Be careful before you going to refactor your code. As in the #NOTE written, jQuery since 1.4 works quite different way. The latest version may contain even more optimizations.
I modified the jsbin code above to have the recent jQuery, and added some additional cases as well. You will see, now only those three (2,3,6) cases got performance penalty which creates one more jQuery object per round. Rest runs in quite same time.
You can find the modified version here: http://jsbin.com/aciji4/63/
精彩评论