Learning JavaScript

This page lists some common misconceptions and solutions to improve JavaScript performance or proper code in general. The intention is to speed up our code base and to make sure code does what it intends. For example  returns true, for starters.

jQuery object instantiation speed (quickExpr)
One of the most common selectors is the ID-selector. In plain javascript we would use  and is the fastest native selector. To avoid initializing all of Sizzle for such a simple thing jQuery has a quickExpr which will filter these out and get them directly.

It does the same for generating HTML fragments. is often faster than. Because the former will use the same and native  function and manipulate that, while the latter will use innerHTML on a temporary node.

The latter also has some pitfalls attached. For example there can never be two loose elements that way (there must be a wrapper around them, will not work as expected). And sometimes the latter will fail in IE7, since it's extra strict about innerHTML assignments and forgetting the in the HTML-string makes it fail in some versions of IE.

Selector performance (jQuery)
Just like the browser's stylesheet engine that parses native CSS, jQuery's selector engine (Sizzle) selects from right to left. Let's understand what this means for the following selector which may look fast / specific but in fact is not.

This particular example may be extreme, but consider the individual tips and tricks.

The above example will initiate the Sizzle engine, starting by getting all anchor tags on the entire page (there's quite a few! Over 1300 on an average edit page on a Wikimedia wiki, don't forget about hidden ones and anchors for javascript actions). After getting all those it will check these one by one to see if their parentNode is a ListItem. If it's not it'll get the parentNode of the parentNode and so on, untill it's all the way to the document.body and gives up and get's started on the next anchor tag. The anchor tags in the Sidebar and in the Personal-area will match for a while for ListItem and UnorderedList and eventually they are dropped when it comes to the. After that it'll still continue for the few anchor tags left, because the selector specifically specifies  as well.

So how to make this more effecient ? The answer is. Context means to get elements instead from within the context of one or more elements, rather than the entire. In plain javascript this is how that goes: So the example given is much faster like this due to context find:

You can optimize even further (depending on your scenario) like this:
 * Dropped the  selector, now we match quickExpr to quickly create a jQuery object.
 * Removed  from the selector. Unless you expect to have invalid ListItems without a list around them or if you specifically need to filter out OrderedLists, there's no need so specify each element in the tree.
 * Added a direct-child expression to speed up the filtering of anchor tags. Ofcourse if your situation may contain  then you don't want this. But whenever you can, use the direct child expression.

Generally one could describe writing more effecient selectors as "Be specific in what you want, and do not baby the selector engine". Specify what you really want, don't add in more crap if that's not what you need (ie. stuff that just happeneds to be the case like the extra "div" in front of the ID and the "ul" in between. Unless, as noted, if you specifically need the "div" or "ul" in which case it's fine to add them in the selector).

Null or undefined
There are more than a dozen ways of comparing or looking at a variable to determine whether it is null or undefined (or either of them). Look at the following for actual performance numbers and decide for yourself what gives the best performance for your scenario:
 * http://jsperf.com/testing-undefined
 * http://jsperf.com/testing-null
 * http://jsperf.com/testing-null-or-undefined

Array
Arrays do not have a  "array". Nor do they validate as "instanceof Array" (atleast not consistently and cross-browser).

As of JavaScript 1.8.5, the array object constructor has an native object method (not a prototype) called "isArray". It can be used like this:

However this is new and not cross-browser yet. The other reliable way to do this to call " " and verify that it is equal to " ". However this is slightly slower.

jQuery has had a built-in object method called "isArray" that does the latter isString comparison that works cross-browser. As of jQuery 1.4 (up to atleast 1.6.1) it only does that if the, faster, native Array.isArray isn't available. The best of both.

So the safest and fastest way to check if a variable is an array is to use.

WikiEditor
Some stuff Catrope discovered when optimizing EditToolbar. These may not be universally true, so when in doubt run both alternatives through the Firebug profiler or use http://jsperf.com


 * Building simple HTML that doesn't need stuff like .data or .click yourself and feeding it to .html or .append is literally about 100 times as fast (YMMV) as building it with jQuery
 * Even if you do need .data or .click, something like this is still faster (at least for 20-200 children, YMMV):
 * Avoid setting .data on hundreds of elements that have a common parent or near ancestor. Instead, add an empty object to the parent's .data and fill that through a reference using the child's rel property as keys. This reduces the number of .data calls a lot.
 * .text is faster than .html if you're only adding text
 * .addClass('foo') is faster than .attr('class', 'foo')
 * but in complex cases involving more attributes and multiple classes, .attr({ ... }); is faster

jQuery.size vs .length attribute
As one can see in the jQuery source, the size function returns the  property of the jQuery object.

As there's no functional difference nor length in number of characters (" " vs. " ") and only a small performance penalty, its use is discouraged.