Declaring a var instead of using .find multiple times? - javascript

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/

Related

How to store and reuse a combination of selector and context expressions in a single variable?

I've recently come to enjoy using this pattern of JQuery selector that I suppose you could describe as a syntactical shortcut for the .find() API:
$('.some-element', '.within-context')
There's a discussion about it on SO here
Anyway, I find myself in the situation where I'd like to store this selector as a variable that I can use in multiple places in my script.
Obviously I can't do this: var selector = '.some-element', '.within-context' as that would just leave me with a variable holding '.within-context'
'.some-element, .within-context' is something entirely different...
And despite sleuthing around the docs and SO, I'm not even sure what this does: $(['.some-element', '.within-context'])
Not really sure what else to try, should I just make two variables?
Consider using the spread operator to expand the $'s arguments from an array. This way you can store a selector combination in an array and pass it later on as two distinct arguments to the jQuery constructor.
For example:
let someSelectorCombo = ['.some-element', '.some-context']; // Store the selector
$(...someSelectorCombo).text('Yay') // Expand the stored selector to two arguments
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="some-context">
<div class="some-element"></div>
</div>
Why not just $('.within-context .some-element')?
Or if you still wanna use context, you can use apply, but I see not much point
var selectorWithContext = ['.some-element', '.within-context'];
$.apply(null, selectorWithContext);

Which is better for efficiency? variabels for repeated selectors or more concise selectors

I'm trying to use variables to store static selectors I use more than once in a specific scope.
These vars would be global variables in that they as all the function definitions and event listeners are directly in jquery's $(function(){ }); scope.
I could make some singular items ids, which I believe is the fastest selector, although too many ids can be bad and don't serve when more than one element needs to be selected.
For any non class nor id (rare), I'm using slightly more complex selectors in jQuery or as js traversing the DOM.
For efficiency, is it best to store all repeated selectors in the highest scope where they will be needed, not always global, or for some of the quicker ones like IDs and Classes, should I make new selectors each time?
I've noticed and heard that tagName selectors can be inefficient, should I give those IDs/classes or make a tagName selector once, store it in a var and use that var repeatedly.
This is only concerning static elements and changes to the DOM would require a new selector to include the new elements.
Caching is always better. So var selected = $("#selected") will always be better than selecting it with jquery every time $("#selected").doSomething().
From: https://code.tutsplus.com/tutorials/10-ways-to-instantly-increase-your-jquery-performance--net-5551
As for storing it in higher scope, the efficiency/speed probably depends how often its called. So if it's used lots, put it in higher scope.

Should I add an 'if' statement to jQuery that doesn't execute on certain pages?

I like to keep my code clean as possible and I am just wondering what would be the best way to go around this problem when it comes to best practices.
I have the following function:
$('.car-hub-header-help, #assistance-overlay').click(function(){
$('#new-car-hub, #new-car-offer').toggleClass('assistance-active');
$('#pulman-assistance').toggleClass('pulman-assistance-active').css("top", fixedPositionCalculator);
$('#assistance-overlay').toggleClass('assistance-overlay-active');
$('#new-car').toggleClass('assistance-active-body');
$('#new-car-offer-cta').toggleClass('assistance-active-cta');
});
Now as you can see this function is very simple it just toggles classes based on a click event. One issue that I am having is that the element new-car-offer-cta is only on specific pages and it seems like this is bad practice to run that part of the function if the element isn't on some of my pages.
So I am just wondering if this would be better practice:
$('.car-hub-header-help, #assistance-overlay').click(function(){
$('#new-car-hub, #new-car-offer').toggleClass('assistance-active');
$('#pulman-assistance').toggleClass('pulman-assistance-active').css("top", fixedPositionCalculator);
$('#assistance-overlay').toggleClass('assistance-overlay-active');
$('#new-car').toggleClass('assistance-active-body');
var carOfferCta = $('#new-car-offer-cta');
if (carOfferCta.length) {
carOfferCta.toggleClass('assistance-active-cta');
};
});
So that part of the function wont run unless the element is on the page. I am just wondering what is classed as the best practice. Thanks
I would advise against doing the check at all. The beauty of jQuery is that you usually don't have to know whether your selector selects 0, 1 or more elements, the methods will just work (even if working is doing nothing at all).
If you start adding these checks everywhere, you're just coupling different parts of your logic more tightly together.
(That's also why I usually prefer not to use id selectors, but select based on classes instead. If then your html changes and e.g. your jQuery code needs to act on more elements, you don't need to change anything in the structure of your page, just apply the right classes.)
jQuery already does that check for you, if the selector inside $() doesn't match any elements, the functions you chain to it won't do anything (not even produce an error). So there's really no need to check explicitly. With these exceptions:
if you want it to be absolutely obvious to anybody reading your code, that the element you're trying to create won't exist on every page that uses your script or
if you want to do a bunch of different things in your if statement,
then it makes sense to explicitly write if ($element.length).
It's better to ask if the element's val is !=undefined, rather than asking for it's length, since that way you're assuming it does exist on the page. You can add the length check right after asking for the element's existence, I usually do as follows:
if($('#new-car-offer-cta').val() != undefined && $('#new-car-offer').val().length > 0){
//do something
}

Is it okay to store the result of a JQuery selector in a variable?

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)...

Most efficient way to re-use jQuery-selected elements

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);
});

Categories