1. XYZ- Javascript Best Practices
For maximizing Front End performance
Avoid inefficient jQuery selectors.................................................................................................................2
Cache selected elements ..............................................................................................................................2
Use delegate() when possible.......................................................................................................................3
Use efficient event delegation......................................................................................................................3
Minimize DOM manipulation........................................................................................................................4
Avoid global variables...................................................................................................................................4
Use Object literals.........................................................................................................................................4
Do not pass strings to setTimeout() or setInterval().....................................................................................5
Optimize string concatenation......................................................................................................................5
De-reference unused objects........................................................................................................................5
Avoid loops if possible, but when needed ensure they are efficient ...........................................................6
Prohibited functions .....................................................................................................................................6
Do not mix CSS with JavaScript.....................................................................................................................6
Optimize Browser Layout Calculation...........................................................................................................7
Validating Code.............................................................................................................................................7
2. Avoid inefficient jQuery selectors
Too general
Use the closest persistent ancestor with an ID to look up an element instead of just a class, which
requires traversing the entire DOM.
$('.className') // Avoid this, it’s slow!
$(‘#someAncestor’).find(‘.className’); // Use this
cachedElement.find(‘.className’); // Or this
Pseudo selectors
These are the slowest selectors to use, there is usually a better way to do what you’re trying to. Avoid
them at all costs.
$('.overlay:hidden') // this takes 200ms in IE8
Attribute selectors
These are also very slow, use a class instead if it is available.
$('select[name=attribute]') // Avoid this
Finding elements with id's within other elements
When an element has an ID, it is always faster to simply select it than searching within another
container.
$('#element).find('#anotherElement') // Avoid this
self.cache.body.find(‘#anotherElement’) // Avoid this
$(‘#anotherElement’) // Use this
Looping elements
Use the good ol’ basic FOR instead of the $.each for looping. It has been proved that the Jquery loop is
slower in performance - http://jsperf.com/jquery-each-vs-for-loop/6
$.each(a, function() {
e = this;
}); // Avoid this
for (var i = 0, len = a.length; i < len; i++) {
e = a[i];
}; // Use this
Cache selected elements
Selecting the same element multiple times causes unnecessary DOM traversal, instead cache the
element in a variable and reuse it.
/* Avoid this */
$(‘#element’).addClass(‘foo’);
// do some stuff
$(‘#element’).removeClass(‘bar’);
3. /* Use this instead */
var myElement = $(‘#element’);
myElement.addClass(‘foo’);
// do some stuff
myElement.removeClass(‘bar’);
Use delegate() when possible
When multiple elements within a persistent container trigger the same action, use delegate() instead of
bind()
<ul id=”myList”>
<li><a href=””>Link 1</a></li>
<li><a href=””>Link 2</a></li>
<li><a href=””>Link 3</a></li>
<li><a href=””>Link 4</a></li>
</ul>
/* Slower */
var myList = $(‘#myList’);
myList.find(‘a’).bind(‘click’,function(){/* doSomething() */});
/* Faster */
var myList = $(‘#myList’);
myList.delegate(‘click’, ‘a’, function(){/* doSomething() */});
Use efficient event delegation
Do not delegate to the body or the document when there is another option. Instead, delegate to the
target’s closest persistent ancestor. Also, delegation is not necessary when you are binding to unique
elements with an id (with the exception of Overlays, or if the unique ID is added/removed from the page
dynamically).
/* Avoid this */
$(‘body’).delegate(‘.someClass’, ‘click’, function(){…});
/* This is better */
$(‘#Main’).delegate(‘.someClass’, ‘click’, function(){…});
/* This is best */
$(‘#closestAncestor’).delegate(‘.someClass’, ‘click’,
function(){…});
4. Minimize DOM manipulation
Accessing and modifying the DOM is very expensive and should be kept to a minimum.
/* Avoid this */
var container = $(‘#container’);
for(var i=0, length = someArray.length; i < length; i++) {
// Modifies the DOM on each iteration of the loop
container.append(‘<li>…</li>);
}
/* Use this instead */
var container = $(‘#container’);
var markupString = ‘’;
for(var i=0, length = someArray.length; i < length; i++) {
markupString += ‘<li>…</li>’;
}
// Only modifies the DOM once
container.append(markupString);
Avoid global variables
Global variables and function names are a very bad idea, and must be avoided. If one needs to be
available to the global scope, they must be a member of a relevant namespace using object literal
notation.
/* Avoid This */
var current = null;
function doSomething() {…};
/* Use this, if there is not already a namespace to use (in most
cases there will be) */
var myNameSpace = {
current: null,
doSomething: function(){};
}
Use Object literals
Objects should never be declared using constructors, doing so is overly verbose and causes a lot of
overhead. Object literal syntax should be used instead.
/* Slower */
var foo = new Object()
foo.bar = 'property';
foo.baz = 'property1';
var fooBar = new Array();
fooBar[0] = 'first slot';
5. fooBar[1] = 'second slot';
/* Faster */
var foo = {
bar: 'property',
baz: 'property2'
} ;
var fooBar = [
'first slot',
'second slot'
];
Do not pass strings to setTimeout() or setInterval()
Instead, pass function names or anonymous functions. A string passed to setTimeout will be executed
globally with eval, which is very slow.
// Slower
setTimeout(‘functionName()’,1000);
// Faster
setTimeout(functionName, 1000);
// Also good
setTimeout(function(){/* doSomething() */},1000);
Optimize string concatenation
Each time the + operator is used, a new string is created in memory and concatenated to the value
assigned to it. Instead, directly build upon the existing variable.
// Slower
a += ‘b’ + ‘c’;
// Faster
a += ‘b’;
a += ‘c’;
De-reference unused objects
Once a variable or element or event-binding is no longer needed, dereferencing it will get ahead of the
JS garbage collection and free up memory. This is especially important for IE
// Delete objects
namespace.foo = { bigData: 'foobar' };
// Do something with namespace.foo
delete namespace.foo;
6. // Detach listeners when no longer needed
someElement.removeEventListener(type, fn, false) // Native
$(someElement).unbind(type); // jQuery
// Remove DOM elements when no longer needed
someElement.parentNode.removeChild(someElement); // Native
$(someElement).remove(); //jQuery
Avoid loops if possible, but when needed ensure they
are efficient
In all program languages, loops should be avoided if at all possible. If they are necessary, keep as much
evaluation or variable creation outside of the loop as possible. Also, cache array lengths in a variable.
Avoid nested loops.
// Slower
for(var i=0; i < someArray.length; i++) {
var container = document.getElementById(‘containerId’);
doSomething();
}
// Faster
var container = document.getElementById(‘containerId’);
for(var i=0, length = someArray.length; i < length; i++) {
doSomething();
}
Prohibited functions
The following have been proven to be inefficient, and should be avoided.
eval()
document.write()
for-in loops
while loops
Do not mix CSS with JavaScript
Whenever possible styling should not be done with JavaScript, unless style needs to change based on
user-interaction. If JavaScript needs to adjust the style of an element, it must do so without
manipulating style attributes directly. Instead, add/remove a CSS class, and allow the CSS to style the
element.
// Slower
$(‘#foo’).attr(‘style’,’color:blue’);
7. // Faster
$(‘#foo’).addClass(‘someClass’);
Optimize Browser Layout Calculation
Setting styles on an element invalidates the browser's layout so that looking up certain style and layout
properties will cause the browser to compute the position of every element on the page. The more
elements on the page, the more costly the calculation. It is possible to minimize the amount of times
this happens.
// Slower
elementA.className = "a-style";
var heightA = elementA.offsetHeight; // layout calculated
elementB.className = "b-style"; // invalidates the layout
var heightB = elementB.offsetHeight; // layout calculated again
// Faster
elementA.className = "a-style";
elementB.className = "b-style";
var heightA = elementA.offsetHeight; // layout calculated
var heightB = elementB.offsetHeight; // layout is up-to-date
Validating Code
Syntactical quality of code must be ran though JSHint - a JavaScript validation tool that gives a detailed
report about syntax warnings and their meaning. Clean and valid code means less confusing bugs, easier
maintainability, and better code security.
http://www.jshint.com/