I can imagine the correct answer to this based on theory, but I'm just looking for some confirmation. I'm wondering what the most efficient way to re-use a jQuery-selected element is. For example:
$('#my_div').css('background','red');
//some other code
$('#my_div').attr('name','Red Div');
vs.
myDiv = $('#my_div');
myDiv.css('background','red');
//some other code
myDiv.attr('name','Red Div');
I assume the second example is more efficient because the element #my_div doesn't have to get found more than once. Is that correct?
Similarly, is it more efficient to first save $(this) in a varaible, such as 'obj', and then reuse 'obj' rather than using $(this) over and over? In this case, jQuery isn't being forced to find an element over and over again, but it IS being forced to convert this to a jQuery object [$(this)]. So as a general rule of thumb, should a jQuery object ALWAYS be stored in a variable if it will be used more than once?
You should write your code such that you limit the number of DOM traversals.
When you write something like this:
$('#my_div').css('background','red');
//some other code
$('#my_div').attr('name','Red Div');
You are finding #my_div twice, which is inefficient.
You can improve this either by assigning the result of a selector (i.e. var x = $('.something')) and manipulate the variable x, or you can chain your method calls like this:
$('#my_div').css('background','red').attr('name','Red Div');
You'll see the above code used a lot, because you're finding the element once. The css() method will apply a CSS style and return the actual result of $('#my_div'), so you can invoke another method, in this case attr().
My preferred way of handling the re-use of selectors is to store them as a variable, and wrap my stuff in a closure.
if you're using jQuery selector (like $('#element')), then yes, you should always store your results.
if you're using object and wrapping it in jQuery (like $(this)), it's not necessary, because jQuery doesn't need to search for that element again.
One thing that I find is generally overlooked is just how powerful jQuery chains are. It may not be so noticeable, but since jQuery caches your wrapped elements within a chain, you can modify elements, go into a more specific subset, modify, then go back up into a a general superset without much overhead.
I expect something like (pardon the example)
$('#myDiv')
.addClass('processing')
.find('#myInput')
.hide('slow')
.end()
.removeClass('processing')
;
to be better performance-wise than even
var $myDiv = $('#myDiv').addClass('processing');
var $myInput = $('#myDiv #myInput').hide('slow');
$myDiv.removeClass('processing');
This also holds for applying the jQuery function to elements returned in an event handler. Try to avoid applying $(...) too many times, because this is slow. Instead create a variable that contains the result of $(...). Good practice is to start the variable with a $, which gives a hint about the jQuery object inside the variable.
$('a').click(function(){
var $this = $(this);
$this.addClass("clicked");
$this.attr("clicked", true);
});
Related
So I encounter this situation often and I want to figure out a better way of going about it. I using the naming convention prefixing my jQuery elements with $ so that I can distinguish them from DOM elements. For example, the following:
$pointers = $('#pointer-box div.pointer');
The problem with that is, if I want to get the 3rd in the result as a jQuery, I have to do
$($pointers[2])
which looks awkward. Unless there's a better way of doing this?
You can use .eq() jQuery method
$pointers = $('#pointer-box div.pointer');
var element=$pointers.eq(2);
Given a jQuery object that represents a set of DOM elements, the .eq()
method constructs a new jQuery object from one element within that
set. The supplied index identifies the position of this element in the
set.
Developers I know tend to call the same JQuery selectors over and over instead of storing the result in a variable. They are consistent with this approach.
For example, they do this:
var propName = $(this).attr('data-inv-name');
var propValue = $(this).attr('data-inv-value');
Instead of this:
var current = $(this);
var propName = current.attr('data-inv-name');
var propValue = current.attr('data-inv-value');
The latter approach feels correct to me but maybe I'm missing something. This is a simple example, but I've seen $(this) repeated dozens of times in the same function.
What is the best practice for development with JQuery? Call selectors repeatedly or store in a variable?
The shown analysis is a micro optimization. Using $(this) repeatedly versus storing $(this) in a variable and reusing it will not cause a significant hit to performance.
The times you really want to store the result is when there is an actual selector in there. The only hit you are taking by repeatedly calling $(this) is calling the jQuery constructor function which is very lightweight.
So in this instance go with what reads better. If there really is a dozen occurrences of $(this) in a row, then there should have either been some storing of the variable as indicated, or more likely there was an opportunity to take advantage of chaining which was missed.
If I'm going to use the same selector more than twice I always create a variable. The one change I would recommend is using $ before your variable name to signify that it is a jQuery object
var $current = $(this);
var propName = $current.attr('data-inv-name');
var propValue = $current.attr('data-inv-value');
In theory selecting the component many times demands more process then using one you already have...
If you don't have too many selectors in your page the diference will be almost null (I guess this is the more commom case)... Then you can think about what makes it more readable or easy to modify...
Sometimes you use the same element in a dozen of lines, in this case I prefer to assign this to a variable because when the element change I will need to change just one line (the line I assigned the variable)...
I have been reading on best practices and I have come across this one:
Dont do this:
$("#element .child").hide()
Do this:
$("#element").find('.child').hide()
Now my question is what if i want to hide/show the .child element multiple times, should I declare it like this:
var spinner = $("#element").find('.child');
spinner.hide();
or do I just keep calling $("#element").find('.child').hide()
Should I declare it like this:
var spinner = $("#element").find('.child');
spinner.hide();
Yes. You should do exactly that since it will obviate the need for multiple dom queries.
One common best practice though, so you can easily keep track of which variables are jQuery objects and which are not, is to prefix your variable with $
var $spinner = $("#element").find('.child');
$spinner.hide();
Yes, create the spinner variable. That way the jQuery constructor/function won't be executed each time, you can reuse the once created objects. The memory overhead is negligible.
That's entirely depending of your problem, if you need to use the same element for multiples purposes in different function, the best options will be to save it into a variable, never the less if you only need once work with chaining of events
Yes, you should always try to keep your selections low, which means that you should save every element selection in a variable that you need more then once.
Try to avoid single DOM operations, also. Let me provide an example:
jQuery('#test').addClass('hide');
jQuery('#check').addClass('hide');
This will add the class "hide" to elements with the id "#test" or "#check". You can apply many jQuery functions like .addClass on element collections also, which will reduce overhead (instead for example iterating over an array / collection with jQuery.each()).
// Select both ids within one query
jQuery('#test, #check').addClass('hide');
This can lead to a huge performance boost if you are really working with the DOM, like adding options to a select box. I've put up a little benchmark on jsfiddle: http://jsfiddle.net/rrgNZ/2/
Here is the code block a
$('ul.filter li').each(function() {
$(this).click(function(e) { //do something });
});
Here is code block b
$('ul.filter li').click(function(e) { //do something });
Don't these do the same thing? is one better than the other? Which one is the better/faster method?
I would assume block b since it has less code but I want to confirm it here, thanks
The effect you see will be the same, but in the first case, every li element is assigned a new function, as you are creating the function object inside the each callback.
In the second case, there exists only one copy of the event handler, which means it uses less memory over all (although this is probably not measurable).
Internally, click calls on (in jQuery 1.7), which is iterating over the elements via each as well:
return this.each( function() {
jQuery.event.add( this, types, fn, data, selector );
});
This is the case with many jQuery methods (most often noted in the documentation), so you are saving characters and memory by letting jQuery implicitly do this.
They would both have the same effect.
I would prefer the second only because it is more concise and you're creating a single anonymous function to handle the click rather than an anonymous function per element.
For Jquery philosophy, the second is better because it is shorter.
Both are more or less same and give the same results. The second code snippet will also internally run each loop and assign the click handler to each li element.
But yes the second code snippet is very clear and simple.
The second usage is called "implicit iteration" and is one of the cornerstones of jQuery.
For example, in JavaScript Definitive Guide, 6th Ed, p.530 for jQuery Basics:
Despite the power of the each() method, it is not very commonly used,
since jQuery methods usually iterate implicitly over the set of
matched elements and operate on them all. You typically only need to
use each() if you need to manipulate the matched elements in
different ways. Even then, you may not need to call each(), since a
number of jQuery methods allow you to pass a callback function.
in http://jqfundamentals.com/chapter/jquery-basics
Implicit iteration means that jQuery automatically iterates over all
the elements in a selection when you call a setter method on that
selection. This means that, when you want to do something to all of
the elements in a selection, you don't have to call a setter method on
every item in your selection — you just call the method on the
selection itself, and jQuery iterates over the elements for you.
Typically, when the library has this built-in as the standard way of doing it, it will be in general better and faster, or else they wouldn't have built it in.
I have a jquery object being passed to my function. In the function I get to one of the sibling. Now how do I apply the .hover to both the objects in one call.
Thanks
Not sure I know exactly what you want to achieve, but something like this?
myObject.siblings('selector').andSelf().addClass('hover');
The selector depends on how you want to find your sibling. You may want to use something like next('selector') or prev('selector'), rather than siblings().
Update
If the second object is not something that can be chained off of the first object, by a simple selector (which you should be able to do if it's a sibling), there's a more general solution.
var jq1 = $('any set of elements');
var jq2 = $('any other set of elements');
var all = jq1.add(jq2);
This way, regardless of how you find jq1 or jq2, they'll be combined into the variable all. From here you can do
all.addClass('hover');
or
all.click();
Working example