Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the cost of '$(this)'?

People here often suggest to cache the jQuery object created from a DOM element, like with this code:

$('#container input').each(function() {
    $(this).addClass('fooClass');
    $(this).attr('data-bar', "bar");
    $(this).css('background-color', 'red');
});
  • Does caching the jQuery object really improve the performance of our code?
  • What happens "behind the scenes" when you pass a DOM element to the jQuery constructor?
like image 425
gdoron is supporting Monica Avatar asked May 03 '12 14:05

gdoron is supporting Monica


3 Answers

In the jQuery tag info this warning appears:

The jQuery function $() is expensive. Calling it repeatedly is extremely inefficient.

Well... that is true only for string selectors, which get parsed with regex to find out what they are:

quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/

Then if the string is a selector (other than id), jQuery traverses the DOM to find a match with its expensive find function:

} else if ( !context || context.jquery ) {
    return ( context || rootjQuery ).find( selector );
}

So yes it's expensive, but that is only true for selectors!

If we pass a DOMElement, the only action jQuery does is saving the DOMElement parameter as the context of the newly created jQuery object and setting the length of the context to 1:

// Handle $(DOMElement)
if ( selector.nodeType ) {
    this.context = this[0] = selector; // Selector here is a DOMElement
    this.length = 1;
    return this;
}

I did some tests with jsPerf, and I found that indeed caching the jQuery object has only a little effect:

Bar chart, described below

In Chrome it's only 7% slower. (In IE it's a little bit more significant: 12%.)

like image 186
gdoron is supporting Monica Avatar answered Nov 19 '22 17:11

gdoron is supporting Monica


To answer your second question, look at the source:

// Handle $(DOMElement)
if ( selector.nodeType ) {
    this.context = this[0] = selector;
    this.length = 1;
    return this;
}
like image 14
SLaks Avatar answered Nov 19 '22 17:11

SLaks


With regard to the performance difference, if you're looking for a direct comparison between the two, it's helpful to remove any extra code that could skew the result, like DOM selection and other methods that aren't directly related.

http://jsperf.com/this-cost/2

enter image description here

In a more real world setting, the relative difference is minor as your test showed

Another thing to keep in mind is that every time you create a jQuery object, memory needs to be allocated for it, which adds to the work that the garbage collector needs to do.

So I think the reason people suggest caching is from somewhat of a principled standpoint. Extra work is being done that, while it usually won't have a noticeable impact, does ultimately require some overhead that can easily be avoided.

like image 10
cliffs of insanity Avatar answered Nov 19 '22 15:11

cliffs of insanity