repeat $() all over the place or declare once and reuse? - javascript

Using jQuery, if I am writing code like this
$('blah').doSomething();
//bunch of code
$('blah').doSomethingElse();
//bunch of code
$('blah').doOtherStuff();
Is a new jQuery object being created each time I say $('blah') ?
If so, would it reduce object creation overhead to do something like this instead:
var blah = $('blah');
blah.doSomething();
//bunch of code
blah.doSomethingElse();
//bunch of code
blah.doOtherStuff();
Make sense?

Absolutely correct!
Why Cache
Another benefit of caching is code maintainability. If the selector is only in one place, changing it only needs to be done in one place. Trust me that makes life easier when maintaining code.
Chain
Although you can go one step further (where relevant), and chain your calls:
$('blah')
.doSomething()
.doSomethingElse()
.doOtherStuff();
This is slightly better for 2 reasons. Firstly, you're not using the extra variable, so you save a tiny amount of memory. Secondly, the language doesn't perform lookups for each identifier use, so it's quicker.
So, why do people still [over]use $()
One reason people use lots of $() is because they don't know any better.
Another reason is because element selection used to be slower. But as with most things in the browser, querying objects with selectors is fast being optimised (document.querySelectorAll), which means it's not such a big deal to cache or not to cache, so maybe with that in mind they allow themselves not to cache.
Finally, there are benchmarks hanging around (one two from a quick google) that try to claim that it doesn't matter or is maybe even faster not to cache. The problem with most of these benchmarks and why I suggest you be very wary about drawing conclusions from them, is that the DOM in the example is not real-world; it's overly simplistic. Secondly, the selectors are simplistic as well. So of course querying will be lightning fast and caching won't make a big difference, but I don't find them at all conclusive.
That said, if your example is similar to those of the benchmarks, then maybe you can draw your own circumstantial conclusions, and caching might just be a nuisance.

Related

Optimizing usage of document.createElement?

function fooBar() {
var creation = document.createElement('div');
creation.appendChild(document.createElement('div'));
}
So up there is a pretty ugly scenario. I often encounter moments where I just want to reuse one of these by cloning or whatever. Im not sure if im overthinking this but something just doesnt seem right. Is it possible to optimize this code?
Rather than continuing conversation in comments, I will simply post an answer.
Short Answer:
It doesn't matter in the slightest.
Longer Answer:
If by optimization you mean execution time, the difference is irrelevant unless you are creating 1000's of elements. If by optimization you mean good DRY code, then I would say your entire approach is incorrect: use templating instead.
The number of possible methods of templating make enumerating them beyond the scope of this answer, but anything from PHP (if that's how you roll) to Handlebars to custom regex replacements will get the job done. But about the only time I call document.createElement is for concurrent script bootstrapping that maintains execution order: see this for more details.
So to summarize, use re-usable templates. If the items need to be created dynamically then use client-side rendering. For everything else, use server-side rendering. Avoid manually creating elements as that's pretty low-level, prefer more abstract solutions like the one I suggested.
how about this one
var creation = document.createElement('div');
creation.innerHTML = "<div></div>";
to get the element
el = creation.querySelector("div");

Is there any performance benefit from caching the document object?

I tend to cache DOM objects used in a given script but recently found myself having to call the document object within a jQuery wrapper. I was wondering if caching $(document) was even worth it considering that there's only one document object per page, which would essentially limit the lookup to one.
Although you're caching it, I'm curious as far as the overall gain if it's called multiple times. I know I'm getting a bit technical but wonder if its more effort on the browser's part to create the variable reference than explicitly writing it out to begin with.
Is there any performance benefit from caching the document object?
Technically yes, but not enough of one to "mandate" caching it for performance reasons. I say "technically" because there is an object allocation and a little bit of logic involved with wrapping the document object as a jQuery object, but it's very cheap. As long as you aren't wrapping it hundreds or thousands of times, just go with whatever makes the code cleaner.

Why is caching values in objects taking more time?

As I have learnt, its better to cache the values in objects which we need repeatedly. For example, doing
var currentObj = myobject.myinnerobj.innermostobj[i]
and using 'currentObj' for further operations is better for performance than just
myobject.myinnerobj.innermostobj[i]
everywhere, like say in loops.. I am told it saves the script from looking-up inside the objects every time..
I have around 1000 lines of code, the only change I did to it with the intention of improving performance is this (at many locations) and the total time taken to execute it increased from 190ms to 230ms. Both times were checked using firebug 1.7 on Firefox 4.
Is what I learnt true (meaning either I am overusing it or mis-implemented it)? Or are there any other aspects to it that I am unaware of..?
There is an initial cost for creating the variable, so you have to use the variable a few times (depending on the complexity of the lookup, and many other things) before you see any performance gain.
Also, how Javascript is executed has changed quite a bit in only a few years. Nowadays most browsers compile the code in some form, which changes what's performant and what's not. It's likely that the perforance gain from caching reference is less now than when the advice was written.
The example you have given appears to simply be Javascript, not jQuery. Since you are using direct object property references and array indices to existing Javascript objects, there is no lookup involved. So in your case, adding var currentObj... could potentially increase overhead by the small amount needed to instantiate currentObj. Though this is likely very minor, and not uncommon for convenience and readability in code, in a long loop, you could possibly see the difference when timing it.
The caching you are probably thinking of has to do with jQuery objects, e.g.
var currentObj = $('some_selector');
Running a jQuery selector involves a significant amount of processing because it must look through the entire DOM (or some subset of it) to resolve the selector. So doing this, versus running the selector each time you refer to something, can indeed save a lot of overhead. But that's not what you're doing in your example.
See this fiddle:
http://jsfiddle.net/SGqGu/7/
In firefox and chrome (didn't test IE) -- the time is identical in pretty much any scenario.
Is what I learnt true (meaning either
I am overusing it or mis-implemented
it)? Or are there any other aspects to
it that I am unaware of..?
It's not obvious if either is the case because you didn't post a link to your code.
I think most of your confusion comes from the fact that JavaScript developers are mainly concerned with caching DOM objects. DOM object lookups are substantially more expensive than looking up something like myobj.something.something2. I'd hazard a guess that most of what you've been reading about the importance of caching are examples like this (since you mentioned jQuery):
var myButton = $('#my_button');
In such cases, caching the DOM references can pay dividends in speed on pages with a complex DOM. With your example, it'd probably just reduce the readability of the code by making you have to remember that currentObj is just an alias to another object. In a loop, that'd make sense, but elsewhere, it wouldn't be worth having another variable to remember.

jQuery - the good parts?

I have embarked on a mission to start using jQuery and JavaScript properly. I'm sad to say that historically I have fallen into the class of developer that makes a lot of really terrible mistakes with jQuery (polluting the global namespace, not caching jQuery selectors, and much more fun stuff - some of which I'm sure I have yet to discover).
The fact of the matter is that jQuery allows people to easily implement some really powerful functionality. However, because everything "just works", performance concerns and best practices immediately take a back seat.
As I've been reading articles on JavaScript and jQuery performance and best practices, I've learned just enough to fully realize how inexperienced I really am. I'm left feeling frustrated because I'm unsure of when I should be using jQuery or just plain JavaScript. The main reason jQuery is so appealing to me is that it takes care of browser compatibility. From what I understand though, there are things you can do with jQuery that you can also do with regular JavaScript that aren't subject to compatibility issues. Basically I'm looking for a guide that explains when using jQuery over regular JavaScript is wise.
A few questions to recap:
Are there parts of jQuery that you shouldn't use due to performance?
What are the parts of jQuery that you should always use to avoid browser inconsistencies?
What are the parts of jQuery that you shouldn't use because there is a reliable and faster way to do the same thing natively in JavaScript?
What are the parts of jQuery that offer multiple ways to do the same thing, with one way being more efficient? For example, the :not() selector versus the .not() method.
I'm looking for existing articles, blog posts, books, videos, etc. I know where the docs are. I read them frequently. I'm hoping for more of an overview that addresses the above issues.
Thanks!
EDIT:
Check out this very similar question: When to use Vanilla JavaScript vs. jQuery?
Wow, I simply cannot believe noone has mentioned storing objects in variables for future use.
Consider this scenario.
You have a complex menu that you're going to write 100 lines of jQuery for.
VERY OFTEN I see something like
$(".menu").fadeIn("slow");
$(".menu li").each(bla bla);
$(".menu li").hover(more bla bla);
if($(".menu").attr('id') == 'menu1') {some hoo ha}
If you're going to reuse an element in jQuery, ALWAYS store it in a variable. It's also common practice to add a dollar sign ($) before the variable name to indicate a jQuery object.
var $menu = $(".menu"); // store once and reuse a million times
var $menu_item = $("li", $menu); // same here
$menu.fadeIn("slow");
$menu_item.each(bla bla);
$menu_item.hover(more bla bla);
if($menu.attr('id') == 'menu1') {some hoo ha}
I definitely say
use the event model as it abstracts the differences across browsers and also provides a means to raise your own custom events too.
don't use .each() or $.each() unneccessarily. Sometimes it can help as it introduces a closure, but often a simple loop will suffice.
the only way to know whether a complicated selector string or a bunch of chained function calls is going to be faster is to benchmark all approaches.
use event delegation when binding the same event handler to more than three elements (I'll see if I can dig out the resource for more than three elements, I seem to remember an article that benchmarked direct binding versus delegation on a number of different factors and found more than three to be the magic numbers).
Above all else, don't worry about performance unless it's a problem. 200ms compared to 300ms, who'll know the difference? 200ms compared to 1000ms, maybe time to look at optimizing something :)
be as specific as possible with your selectors and help those poor older versions of IE out.
Several of your questions focus on performance.
As a rule, jQuery cannot possibly perform better than the underlying native Javascript. jQuery does not interact directly with the browser or operating system; it's just providing a wrapper around built-in Javascript functions. So at an absolute minimum calling a jQuery function incurs the overhead of an extra function call.
In many cases, jQuery is indeed doing quite a bit of heavy lifting in order to produce a result, when hand-written "pure" Javascript might be able to avoid that work.
The point of the framework is to make the programmer's life easier, and historically everything that's ever made programmers' lives easier cost performance. Hand-written machine language is almost universally more efficient than the best compiled code ever assembled.
So the best answer to your questions about performance is: don't worry about it. If you ever encounter a performance problem, then consider jQuery as one possible target for optimization.
As far as browser inconsistencies, one of the major purposes of the framework is to avoid them entirely. There have been bugs historically where certain features didn't work in one browser or another, but these were bugs specific to a particular version of the library. So avoiding them entirely wouldn't be quite the right solution. And trying to identify them here (rather than jQuery's own bug reports) would make this discussion almost instantly out of date.
Nowadays, the primary rule of thumb with javascript is that it has wicked-fast execution time (on non-ie modern browsers), but dom access/manipulation is crazy slow. The faster the JS runtimes get, the more the DOM becomes the bottleneck.
As a rule, you shouldn't really overly worry about performance until it becomes an issue, since most code doesn't need to be fast, and you usually don't know where the problems will be until you test it. That being said, try to minimize dom interaction wherever you can.
as a side note, idiomatic jquery is using javascript the right way. Favor composing functions over OOP, use closures for encapsulation, don't mix javascript handlers (or heaven forbid, script blocks) in your html, and treat objects as property bags that you can attach or detach things to at will.
I'm no expert but I learnt a couple of things.
Don't abuse HTML attributes, that means don't store your intended roll-over images in a rel/rev, use a background image instead. This also helps with the performance of roll overs in IE, as IE doesn't like it when you are changing the src attribute on the fly.
Also hover-intent is very useful to have instead of just using .hover :)
My two cents: do not underestimate the power of the jQuery team (Resig an Co.)---their intent is not to lead you easily into performance gotchas. That being said, here's one: when you use a selector (which is the query in jQuery), do insure to use [context].
So let's say you have a table with 243 rows---and you have not tagged each tr with an id (because you are cool). So you click, say, a button in a row with an event. The event for the button needs to search the current row for a select widget. The innards of the click() event might have these lines:
var tr = $(this).closest('tr'); //where $(this) is your button
$('td select', tr).css('color', 'red');
So the last line there does a search for select elements in the context of a table row (tr). This search means to be faster than searching the entire table (or the entire page) for an id or something similar.
What is also implied here is that I'm putting my trust in the jQuery team that their implementation of the jQuery.closest() method is fast and efficient. So far, I've no reason not to have this trust.

jQuery optimization - anything wrong with storing a jquery object reference?

I have a web-based application which is very highly reliant on jquery / javascript, and its sometimes a bit slow. One of the things that gets done frequently is changes to the grid (jqGrid) which means each time I'm using jQuery to select that object, ie:
function load_editor() { $('#listview').jqGrid(do_stuff); }
I believe simply storing a reference to $('#listview') - since its used in a half dozen functions - would be quicker. So is there any drawback to setting it up like this:
listview = $('#listview');
function load_editor() { listview.jqGrid(do_stuff); }
It would seem this way common objects are already in memory, and wont incur the penalty of the lookup on each use. Is there any downside to structuring this way?
( I'm aware in my examples, I'm throwing out a global. Its all nicely encapsulated in an object in the actual project, I just am using these examples to illustrate my point. )
Absolutely you should.
And I strongly recommend you follow the style of the linked article - name your jQuery object variables with a $ prefix. Knowing which of your variables are jQuery objects just by looking at them will be of great help to you when your project becomes large.
There's nothing wrong with it, and in fact it's a great idea in critical code. However, the Sizzle engine is really fast, so you should consider the sort of mess you might be making with lots of such variables and whether the performance benefit is worth it.
Of course if your DOM changes a lot, you need to be careful that what you've got saved remains valid across DOM updates.

Categories

Resources