views:

176

answers:

6

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!

+5  A: 

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.

VoteyDisciple
+2  A: 

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.

Russ Cam
A: 

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

Noctine
A: 

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.

Matt Briggs
A: 

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.

rasx
"This search means to be faster than searching the entire table (or the entire page) for an id", false, false, false. Selecting by id will always be faster
redsquare
Okay: I'll make sure to use IDs for every element (actually I won't)... by the way, where's the guidance at jquery.com backing you up?
rasx
Jeff Atwood: "short story: finding an element by id is much faster than the other methods -- at least in that test" [http://stackoverflow.com/questions/46214/good-ways-to-improve-jquery-selector-performance]
rasx
"For id selectors, jQuery uses the JavaScript function document.getElementById(), which is extremely efficient." However: "...When another selector is attached to the id selector, such as h2#pageTitle, jQuery performs an additional check before identifying the element as a match." [http://api.jquery.com/id-selector/]
rasx
+1  A: 

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}
Marko
I mentioned it in my question ;)
Bryan Downing