Find Versus Context
Everyone has heard that we should scope our requests in jQuery to make sure and only return results that we are looking for. This is especially true if we are writing a plugin. And lately I have been hearing we should be using .find() to get the elements we are looking for.
Of course, that peaked my interest. Why use .find() which I had heard was slower, than using $(“”, context) which scopes the call in much the same way in jQuery. So I set off to write a Performance Test that would check to see which one I should be using.
Setting up the Test
You can see the test here: JSPerf jQuery Find Versus Context versions 1-4-2 to 1-5
I wanted to test 3 of the latest versions of jQuery, plus the browsers native docuemnt.getElementById(). so I added the following to the test:
var $15 = jQuery.noConflict();
var $144 = jQuery.noConflict();
var $142 = jQuery.noConflict();
var context5 = $15("div.wrapper");
var context44 = $144("div.wrapper");
var context42 = $142("div.wrapper");
Notice that I am going to set a variable for each of the individual jQuery versions. This allows me to use multiple version in the noConflict() state. (They won’t overwrite each other and I will be able to have all of them on the same page.) Also, I setup a couple of variables that I want to cache the results. If we had to call this for each of the tests, we wouldn’t get an accurate result between a find and context search.
So lets setup the actual tests:
//Get - document
var item = document.getElementById("button");
//Get - ID 1.4.2
var item = $142("#button");
//Get - ID 1.4.4
var item = $144("#button");
//Get - ID 1.5
var item = $15("#button");
//Context - ID 1.4.2
var item = $142("#button", context42);
//Context - ID 1.4.4
var item = $144("#button", context44);
//Context - ID 1.5
var item = $15("#button", context5);
//Find - ID 1.4.2
var item = context42.find("#button")
//Find - ID 1.4.4
var item = context44.find("#button")
//Find - ID 1.5
var item = context5.find("#button")
//Get - Class 1.4.2
var item = $142(".buttonRef");
//Get - Class 1.4.4
var item = $144(".buttonRef");
//Get - Class 1.5
var item = $15(".buttonRef");
//Context - Class 1.4.2
var item = $142(".buttonRef", context42);
//Context - Class 1.4.4
var item = $144(".buttonRef", context44);
//Context - Class 1.5
var item = $15(".buttonRef", context5);
//Find - Class 1.4.2
var item = context42.find(".buttonRef")
//Find - Class 1.4.4
var item = context44.find(".buttonRef")
//Find - Class 1.5
var item = context5.find(".buttonRef")
Each one of the tests above will run and the result will be returned in Ops/Sec. At this point, we are going to run a test to figure out how fast a context.find(“”), $(“”, context) take for an ID and for a class. I also added in a default document.getElementById() to test how fast natively the browser is able to get a Node Element.
After runs in all different versions of the browsers we have a fairly good idea of the results. Take a look below.
Find a class element Results
In General this test held true. Using find in all but FF3 and Opera is a faster way to find an element using a class.
Find an element by ID Results
WOW, not what I expected. Not one browse was a find faster than just using $(“#someID”). Basically this all boils down to how jQuery treats an ID selector. It doesn’t use the sizzle engine to query the Node Element, but uses the browsers built in document.getElementById(). However, if you pass in a context jQuery will use the engine to make sure the element falls within the context you are using.
Find an element using built in getElementById() Results
Ok, so this result really confused me after seeing the jQuery $(“#someID”) results. I wasn’t expecting there to be such a discrepancy in operations per second. After seeing this result, I actually started putting together another post. Which will end up the second part of this series.
It should be noted that Chrome, Opera, Safari and FF are all doing well over a million operations per second in this area.
After seeing the results above, I thought we needed one more graphic showing the extremely bad numbers IE put up in this test. There was no noticable change between IE6 and IE7, and while IE8 is better, its still bad. However, it looks like the IE9 team is finally taking web development seriously and trying to make some improvements. Of course those improvements still fall WAY short of any of the other browsers on the market.
Come on IE team, haven’t we learned anything from the IE6 debacle?
Overall, the conlusion here is to never use a context based find/search for an ID. (since there is always only one on the page… right?) If you need to get an element using an ID, just call it via $(“#someID”).
IF you need to get a class element(s), follow this rule:
context.find() > $(“.someClass”, context) > $(“.someclass”);
Next Article >> $(“#ID”) is fast enough