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, until 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 efficient ? 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 to 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 happens 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

The fastest way to check if an (un)passed argument or object property is undefined is by strictly comparing it to the  literal.
 * Argument or object property undefined

So why do people use ? It's often used to avoid throwing a ReferenceError if the variable was undeclared. However in many cases a variable is not considered undeclared but undefined. The two can be confusing, but once you know it could make your code cleaner, simpler and faster.
 * Variable undeclared

Arguments and object properties are never considered undeclared. The only scenario in which referring to a variable throws an exception is when the (local or implied global) variable itself is not declared anywhere before.

This is no different when comparing to :

Only in these situations a typeof is needed to check it's type before accessing the variable itself.

Although the above situation may seem common (and perhaps is), in good quality code it should be rare if not absent entirely. Reason being that global variables should be accessed through the  and thus never throw a ReferenceError. And local variables are under your direct control, if those are undeclared something went horribly wrong! Consider the following construction: One has to use  because   could be undeclared. However, this is generally a bad way to define a variable. You can declare (without defining) the variable ahead of time: This also makes the code a lot cleaner and shorter. It also makes it's scope clear beyond a doubt. JsHint and JsLint occasionally spit out warnings as well when a variable is not declared before it is defined within an if-statement (for good reasons, as shown above).

Providing default values / fallbacks for variables doesn't need a typeof check either. Or even, if your argument won't / shouldn't be false-y:
 * Fallback

Verifying a variable to be either 'null' or 'undefined' (like  in PHP) can be done by a loose  comparison to null, which returns true for null as well as for undefined.
 * 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.