JavaScript Performance Tips






4.72/5 (10 votes)
Some useful tips on JavaScript code performance
Introduction
In this tip, I have tried to capture the common design and coding mistakes JavaScript developers tend to make. The intended audience for this article is JavaScript beginners with a few years of programming experience.
Background
Over the years, I have observed how web based Enterprise/Consumer software is designed, developed and tested. One common trait in all of these applications is the usage of JavaScript. More often than not, developers either overlook or are ignorant about JavaScript performance. This is partly because these days, the machines are mostly high end and the browsers with their ever improving script engines have to some extent camouflaged the performance aspect. So developers are not penalized for writing bad JavaScript. Nevertheless if developers follow certain discipline while coding JavaScript, they'll definitely notice that their app will improve in terms of performance and maintainability.
Tips on Performance
- Always prefer the Single
var
pattern. JavaScript Engine hosts all thevar
s to the top of the function. So even if we declare ourvar
at the bottom of the function, it doesn’t matter. Remember JS isn’t compiled into a binary! In the example below, both functions are the same but the second one is optimal. - Do not use
for
-in
loop to iterate over arrays. Usefor
loop instead.for
-in
loops should be used to iterate user defined object literals. The example below takes more time to execute in comparison with a simplefor
loop. - Avoid returning undeclared variables from a function.
- Cache your objects whenever possible.
- Return
this
from your initializer to facilitate chaining. In the below example, we are able to calldoAjax
oninit
because we induced chaining by returningthis
. - Avoid nesting deep inside a function. Well, this applies to any programming language.
- Avoid memory leaks and circular references in your closures. Developers typically tend to write the code below:
function foo() {
var c = 1;
//lots of logic
//and then
var d = 0;
var e;
}
function foo() {
var c = 1, d = 0, e;
}
//Takes more time
var i, b, c;
for (i in c=[1,2,3]) {
b = c[i];
if(b === "x")
DoSomething();
}
For
-in
loop iterates over every property, even the prototype! So
in the example above, it loops through all properties of c.prototype
and in case
c.prototype
has a property called ‘prop
’, it also iterates over
c.prototype.prop.prototype
, etc. This clearly is not necessary if all we want is to loop through an array.
function foo(a, b) {
r = a + b;
return r; //creates a variable r in global scope!
}
//Good
for (var i = 0, x = p.length; i<x; i+=1) {
}
//Better
for (var i = 0, x; x= p[i]; i += 1) {
}
Even when you use libraries like jQuery, YUI, MooTools, etc., ensure that you cache the selector. Remember DOM Traversal is costly!
function foo() {
var d = $("#myDiv"), c = $("#myDiv:firstchild");
//.....
//Use d and c later whenever needed!
}
var MyApp = {};
MyApp.Utilities = (function () {
return {
init: function (a,b,c) {
//initialize your stuff
return this;
},
doAjax: function() {
}
};
})();
MyApp.Utilities.init().doAjax();
Note: If you have a constructor for your class, you don’t have to return this
explicitly. Constructors always return this
.
//Not recommended
function successCbk(r) {
if (r) {
if (r.data) {
if (r.data.myProp) {
//Do something
} else {
}
}
}
}
//Better!!
function successCbk(r) {
if (!r) return;
if (!r.data) return;
if (r.data.myProp) {
//Do something
} else {
}
}
//Classic case for circular references
function foo(e,d) {
$(e).on("click", function() {
//Do something with d
});
}
The problem with the code above is that the click callback closure for the element e
keeps a reference to both
e
and d
even though it just uses d
. Similarly, e
also keeps a reference to the closure thus creating a circular reference. These functions will never be
garbage collected. The trick is to break this chain!
//Break the cycle!
function foo(e, d) {
$(e).on("click", cbk(d));
}
function cbk (d) {
}
Parting Note
If you find this tip useful, please share it with the developer community. I haven't executed every line of code in this tip, so in case you find discrepancies, please comment on the post. I'll incorporate the changes as soon as possible.
Happy learning. :)