In my opinion, one of the best jQuery performance tips is to minimize your use of jQuery. That is, find a balance between using jQuery and plain ol’ JavaScript, and a good place to start is with ‘this‘. Many developers use $(this) exclusively as their hammer inside callbacks and forget about this, but the difference is distinct:
When inside a jQuery method’s anonymous callback function, this is a reference to the current DOM element. $(this) turns this into a jQuery object and exposes jQuery’s methods. A jQuery object is nothing more than a beefed-up array of DOM elements.
Digging a little deeper
As you begin to nest functions the context of this changes:
<a href="#"><span>Hello World</span></a> $("a").click(function(event){ var self = this; $(this).find("span").each(function(){ console.log(self, this); }); event.preventDefault(); });
In this example I save this to the variable “self” so it can be referenced inside the each() loop. Otherwise it’s impossible to reference this as the anchor element inside the loop, because this is now the “span” DOM element.
Depending on what you’re doing, using this is sometimes easier and always faster than $(this). I’m not talking about scraping jQuery altogether, but rather recognizing that a lot of DOM interaction (especially the simple stuff) can just as easily be done in vanilla JS using this; you are not required to use the jQuery API. Example:
<a href="test.htm">Test</a> $("a").click(function(){ var href = this.href; // the href property can be accessed through 'this' });
A more verbose example demonstrating the uses of this and $(this) to get an anchor’s href value. These statements are equivalent:
$("a").click(function(){ var href; href = this.href; // sets "href" to "test.htm" href = $(this).attr("href"); // also sets "href" to "test.htm" after going through the jQuery attr() method. // because $(this) is really just a beefed-up array, we can pull off the DOM element using array notation. href = $(this)[0].href; });
The point here is that turning this into a jQuery object and using the attr() method is more time consuming than just referencing the “href” property of this. When manipulation is involved the performance implications are even greater.
Benchmarks
To quantify my claims, I wrote a profiling function that calculates the execution time of looping a block of code 50,000 times:
var profile = function(label, code, iterations){ var start, total, i = iterations = iterations || 50000; start = (new Date).getTime(); while(i--){ code.call(); } total = (new Date).getTime()-start; console.log(label + ': %d ms (looping %l times)', total, iterations); }
I then setup a page with one anchor element and a click event to call the profile function:
$("a").click(function(event){ // save $(this) and 'this' - their reference change inside the profile function! var $this = $(this), self = this; console.log('Accessing the href attribute of a link:'); profile('$this.attr("href")', function(){ href = $this.attr("href"); }); profile('self.href', function(){ href = self.href; }); profile('self.getAttribute("href")', function(){ href = self.getAttribute("href"); }); event.preventDefault(); });
Update 1/7/2010: JAlpino pointed out in the comments that the getAttribute(“href”) method can be called on this to gain an additional +/- 350ms, as opposed to using this.property syntax. I’ve added this method to the benchmarks & results. Thanks, JAlpino!
The results using jQuery 1.3.2 and 1.4a2 respectively on Firefox 3.5.6:


self.href provides a 270% improvement when using jQuery 1.3.2 and a 200% improvement when using 1.4a2. Using the getAttribute() method provides an additional 72% boost over self.href! Keep in mind that in ‘the jQuery way’ these numbers do not include the time it takes to convert this into a jQuery object; we’re caching that outside the profile function, and thus are only benchmarking the performance of the attr() method. How does this perform over $(this) when used for manipulation? I ran the profiler again, this time changing the link color to red:
profile('the jQuery way', function(){ $this.css("color", "#ff0000"); }); profile('vanilla javascript', function(){ self.style.color = "#ff0000"; });


We’re looking at a 632% improvement under jQuery 1.3.2 and a 206% improvement under 1.4a2. Pretty good for changing one line of code.
Putting this into context
You can pass an optional second argument called context to the jQuery object constructor, which gives jQuery a starting point when searching the DOM for your selector. The context can be either a DOM element or jQuery object, but ideally should be a DOM element – like this! Given the markup below and what we know about this and $(this), the “span” child of the anchor can be found four ways:
<a href="testing.htm"><span>test link</span></a> $("a").click(function(){ // these statements accomplish the same thing $(this).find("span"); $("span", this); $("span", $(this)); $("span", $(this)[0]); });
The first example turns this into a jQuery object and calls the find() method. The second example looks for a span element using this – a reference to the anchor DOM element – as the starting point. Because the context argument in the third example is a jQuery object, jQuery internally converts the statement to $(this).find(“span”), which is equivalent to the first example. We’re about to see that this is the slowest method, however, probably due to the overhead in converting the context to a find(). The fourth method is equivalent to $(“span”, this), except that this is first converted into a jQuery object, and then the DOM node is pulled off the array.
My original plan going into this blog post was to show you the performance benefits you can gain when using this as the context argument to the jQuery constructor as opposed to $(this), but my results show otherwise. Note that I ran these tests 20,000 times instead of 50,000 (Firefox got cranky):
$("a").click(function(event){ // cache $(this) and 'this' var $this = $(this), self = this; profile(' $this.find() ', function(){ $this.find("span"); }, 20000); profile(' $("span", this) ', function(){ $("span", self); }, 20000); profile(' $("span", $this) ', function(){ $("span", $this); }, 20000); profile(' $("span", $this[0]) ', function(){ $("span", $this[0]); }, 20000); event.preventDefault(); });


When using jQuery 1.3.2, $(this).find() was 4% faster than providing a DOM element as the context and 53% faster than using a jQuery object – pretty negligible. 1.4a2 shipped with some nice speed improvements; the performance of all four are about the same, but $(this).find() is still a bit faster.
To reiterate, I’m not saying skip jQuery and code everything in plain JS because it’ll make your site faster. The speed improvements I pointed out are trivial but can absolutely add up, especially in larger applications. There are a number of good reasons to use $(this) over this; cross-browser compatibility is one, the extreme ease of use another, but just be aware this exists.
Click here to see the code and run these benchmarks yourself.
Related posts:









Nice article! It was surprising to see the vast difference in performance overhead for wrapping dom reference, I wonder if the same benchmarks follow through in other browsers like Chrome, IE, etc..
As an fyi, the links to run the benchmark tests comeback with a 404 (/this/testing.htm)
Thanks – the link’s fixed. Just a note that the performance overhead is in using jQuery methods vs. plain JS, not just wrapping a DOM reference.
yeah, I should have articulated my response a little better. I realized that the overhead was in using jQuery and not simply by “wrapping [the] dom reference”.
I decided to run the tests in both Chrome(3.0.195.38) and in IE(8.0.6001.18702). The results in IE were similar to your runs in FF (although slower overall), but in Chrome the performance difference was magnified! Chrome seemed to run about 275% faster than FF on the baseline vanilla javascript stuff, where as jQuery didn’t see the same kind of improvement making the difference in performance greater.
I will probably be keeping a closer eye on calls that can be swapped out in place of it’s jQuery counterpart going forward.
btw, here are my runtimes from the test http://pastebin.com/m3557855f
Nice Article! One limitation of using this directly is that the number of attributes supported are very minimal. Take the label tag for instance. It has an attribute “for”. this.for does not execute. In fact it gives a JavaScript error. Then there is also a question of consistency. It will take greater effort in ensuring that this is being used directly correctly, especially when working in large teams.
@JAlpino nice! This calls for a graph, I’ll have to whip one up. I’m real surprised there was no improvement in Chrome using jQuery vs. JavaScript.
@Kartik good point. It’s harder to see what is available to ‘this’ because, unlike a jQuery collection, logging it to the console doesn’t reveal it’s properties.
@Kartik Just wanted to point out that you can use the getAttribute() and setAttribute() methods on the dom node to get around the lack of a ‘public’ property such as ‘for’ on a label.
Another interesting point is that in all browsers that I tested this on; FF(3.5.6), Chrome(3.0.195.38) and IE(8.0.6001.18702), getAttribute() performed much better (4x) than straight object.property notation.
Add the following profile statement to the first test:
** setAttribute() on the hand, had mixed results. In FF in ran in the same time as the object.property = ‘value’; notation, but in Chrome and in IE it was much slower.
Wow, I cannot believe getAttribute() is that much faster… I’ve added this benchmark to my original post. I did some research and found a good post on the differences between this.property and this.getAttribute(): http://updatepanel.wordpress.com/2008/12/31/more-on-getattribute-setattribute-and-the-value-attribute/
As it turns out, getAttribute() will return the string value set in the original markup regardless if it is changed later by JS. this.property notation returns the current value. Just something to be careful of…
@Eric Thanks for sharing this information. I was not sure if getAttribute was faster on all the browsers, but I too faced problems similar to the ones mentioned in http://updatepanel.wordpress.com/2008/12/31/more-on-getattribute-setattribute-and-the-value-attribute/ when trying to use getAttribute and setAttributes while sorting list boxes.
Seeing all the qualifiers, this seems to prove the point that jQuery (and other, similar libraries) is invaluable to developers writing cross-browser JS. Thanks for the reminder, though, that libraries also invisibly add cycles. It won’t affect us much when developing sites with minimal JS that’s executed once or even on occasional user interaction, but when writing complex web apps, knowing how to optimize the code that gets executed repeatedly will save your users lots of headaches.
Wow, thanks for the great tip, there were a couple of things I didn’t know!
Sure, but this is for 20-50k times. I don’t have any functions that are called that many times.
Like any type of app development, it’s best not to get caught up in pre-mature optimization. So @Adam, if your app is not heavy on the client side, then taking optimization steps such as using the dom properties directly vs. jQuery calls, then it might not make sense to switch. However, if that’s not the case then applying these performance measures will help, even if the calls span over time rather than all at once.
Regarding premature optimization, I don’t think anyone is claiming to refactor code to use this approach. I do, however, feel its prudent as a client side coder to know where performance can be improved, without taking away from the readability. While many of us are on quad core machines that show minute differences with events. Its very likely a user could be on an older machine that stands to gain.
I agree with premature optimization being an unnecessary step in the development cycle, but with this new knowledge, it instead becomes good practice.
I also noticed through some testing of my own that getElementsByTagName performed faster than access forms and images through dot-notation.