Walkthrough On Javascript Coding Standards and Best Practices
Walkthrough On Javascript Coding Standards and Best Practices
Prepared By:
Devaraja H
Divya K S
Gowtham
Change Record
Reviewers
Table of Contents
1 Javascript Coding Standards ................................................................................................................. 5
1.1 JavaScript Files .............................................................................................................................. 5
1.2 Whitespace ................................................................................................................................... 5
1.3 Comments ..................................................................................................................................... 6
1.4 Variable Declarations .................................................................................................................... 6
1.4.1 Avoid Global Variables .......................................................................................................... 6
1.4.2 Always Declare Local Variables ............................................................................................. 7
1.4.3 Declarations on Top .............................................................................................................. 7
1.5 Function Declarations ................................................................................................................... 7
1.6 Names ........................................................................................................................................... 8
1.7 Statements .................................................................................................................................... 8
1.7.1 Simple Statements ................................................................................................................ 8
1.7.2 Compound Statements ......................................................................................................... 8
1.7.3 Labels .................................................................................................................................... 9
1.7.4 return Statement .................................................................................................................. 9
1.7.5 if Statement .......................................................................................................................... 9
1.7.6 for Statement ........................................................................................................................ 9
1.7.7 while Statement .................................................................................................................... 9
1.7.8 do Statement ...................................................................................................................... 10
1.7.9 switch against if : Statement .............................................................................................. 10
1.7.10 try Statement ...................................................................................................................... 10
1.7.11 continue Statement ............................................................................................................ 10
1.7.12 , comma Operator ............................................................................................................... 11
1.8 Assignment Expressions .............................................................................................................. 11
1.9 Confusing Pluses and Minuses .................................................................................................... 11
2 JavaScript Best Practices ..................................................................................................................... 12
2.1 Use === Instead of ==.................................................................................................................. 12
2.2 Avoid using Eval .......................................................................................................................... 12
2.3 Utilize JS Lint ............................................................................................................................... 12
2.4 Place Scripts at the Bottom of Your Page ................................................................................... 12
JavaScript Best Practices
2.5 Declare Variables Outside of the For Statement ........................................................................ 13
2.6 Use native methods to build String in a faster way .................................................................... 13
2.7 Reduce Globals............................................................................................................................ 14
2.8 Comment Your Code ................................................................................................................... 14
2.9 Use function instead of passing String to "SetInterval" or "SetTimeOut" ................................. 14
2.10 Don't Use the "With" Statement ................................................................................................ 15
2.11 Use {} Instead of New Object().................................................................................................... 15
2.12 Use [] Instead of New Array()...................................................................................................... 16
2.13 For Long List of Variables use Commas Omit the "Var" Keyword .............................................. 16
2.14 Always Use Semicolons ............................................................................................................... 16
2.15 Use Firebug's "Timer" Feature to Optimize Your Code .............................................................. 17
2.16 Use object.hasOwnProperty() to filter/retrieve direct properties of that object ...................... 17
2.17 Use self-executing functions to run when page loads or parent function is called.................... 17
2.18 Check if Callback is defined and is executable before trying to run it. ....................................... 18
2.19 Raw JavaScript Can Always Be Quicker Than Using a Library ..................................................... 18
2.20 Add methods to class(Object)’s prototype than defining them internally. ................................ 19
2.21 Place instance variable declaration/initialization on the prototype for instance variables ....... 20
2.22 Avoiding pitfalls with closures .................................................................................................... 21
2.23 Be careful when using typeof, instanceof and constructor. ....................................................... 22
2.24 Don’t use delete to remove an item from array, instead use the splice. ................................... 22
2.25 Truncate an array using length property. ................................................................................... 23
2.26 Use logical AND / OR for conditions ........................................................................................... 23
2.27 Use a switch/case statement instead of a series of if/else......................................................... 24
2.28 Avoid using try-catch-finally inside a loop .................................................................................. 24
2.29 Set timeouts to XMLHttpRequests.............................................................................................. 25
2.30 Primitive operations can be faster than function calls. Use VanillaJS. ....................................... 25
2.31 Namespace your JavaScript if you need to refer to it elsewhere. .............................................. 25
2.32 Anonymously scope JavaScript if you’re never going to call it elsewhere. ................................ 25
2.33 When optimizating, focus on the big things. .............................................................................. 26
2.34 unbind() all event handlers before binding. ............................................................................... 26
2.35 jQuery.......................................................................................................................................... 27
JavaScript Best Practices
2.35.1 Prefix jQuery object variables with a $. .............................................................................. 27
2.35.2 Cache jQuery lookups. ........................................................................................................ 27
2.35.3 For DOM queries use Cascading $('.sidebar ul') or parent > child $('.sidebar > ul'). .......... 27
2.35.4 Use find with scoped jQuery object queries. ...................................................................... 28
3 JavaScript Perfomance keys ................................................................................................................ 29
3.1 Avoid interaction with host objects ............................................................................................ 29
3.2 Manage and Actively reduce your Dependencies ...................................................................... 32
3.3 Be disciplined with event binding ............................................................................................... 34
3.4 Maximise the efficiency of your iterations ................................................................................. 36
3.5 Become friends with the JavaScript lexicon ............................................................................... 38
JavaScript Best Practices
All code in any code-base should look like a single person typed it, no matter how many people
contributed. Arguments over style are pointless. There should be a style guide, and you should follow
it.
Coding conventions :
JavaScript code should not be embedded in HTML files unless the code is specific to a single session.
Code in HTML adds significantly to pageweight with no opportunity for mitigation by caching and
compression.
Use lower case file names to be consistent across different web servers as most of them are case
sensitive about file names, even small errors can break the website.
1.2 Whitespace
Where possible, these rules are consistent with centuries of good practice with literary style. Deviations
from literary style should only be tolerated if there is strong evidence of a significant benefit.
Blank lines improve readability by setting off sections of code that are logically related.
Blank spaces should always be used in the following circumstances:
A keyword followed by ( left parenthesis should be separated by a space. Spaces are used to make
things that are not invocations look less like invocations, so for example, there should be space after
if or while.
while (true) {
A blank space should not be used between a function value and its invoking ( left parenthesis. This
helps to distinguish between keywords and function invocations.
The word function is always followed with one space.
No space should separate a unary operator and its operand except when the operator is a word
such as typeof.
All binary operators should be separated from their operands by a space on each side except . period
and ( left parenthesis and [ left bracket.
Every , comma should be followed by a space or a line break.
Each ; semicolon at the end of a statement should be followed with a line break.
Each ; semicolon in the control part of a for statement should be followed with a space.
JavaScript Best Practices
Every statement should begin aligned with the current indentation. The outermost level is at the
left margin. The indentation increases by 4 spaces when the last token on the previous line is { left
brace, [ left bracket, ( left paren. The matching closing token will be the first token on a line,
restoring the previous indentation.
The ternary operator can be visually confusing, so ? question mark always begins a line and increase
the indentation by 4 spaces, and : colon always begins a line, aligned with the ? question mark. The
condition should be wrapped in parens.
Avoid excessively long lines. When a statement will not fit nicely on a single line, it may be necessary
to break it. It is best to break after a { left brace, [ left bracket, ( left paren, , comma, or before a .
period, ? question mark, or : colon. If such a break is not feasible, then break after an operator and
continue on the next line with 8 spaces added to the current indentation. Those 8 spaces do not
change the current indentation.
Clauses (case, catch, default, else, finally) are not statements and so should not be indented like
statements.
1.3 Comments
Be generous with comments. It is useful to leave information that will be read at a later time by
people (possibly your future self) who will need to understand what you have done and why.
It is important that comments be kept up-to-date. Erroneous comments can make programs even
harder to read and understand.
Make comments meaningful. Focus on what is not immediately visible.
This will:
function outer(c, d) {
var e = c * d;
function inner(a, b) {
return (e * a) + b;
}
This convention works well with JavaScript because in JavaScript, functions and object literals can
be placed anywhere that an expression is allowed. It provides the best readability with inline
functions and complex structures.
function getElementsByClassName(className) {
var results = [];
walkTheDOM(document.body, function (node) {
var array; // array of class names
var ncn = node.className; // the node's classname
JavaScript Best Practices
// If the node has a class name, then split it into a list of simple names.
// If any of them match the requested name, then append the node to the list of results.
If a function literal is anonymous, there should be one space between the word function and the
( left parenthesis. If the space is omitted, then it can appear that the function's name is function,
which is an incorrect reading.
that = {
method: function () {
return this.datum;
},
datum: 0
};
1.6 Names
Always use the same naming convention for all your code. For example:
Names should be formed from the 26 upper and lower case letters (A .. Z, a .. z), the 10 digits (0 ..
9), and _ underbar. Avoid use of international characters because they may not read well or be
understood everywhere. Do not use $ dollar sign or \ backslash in names.
Variable and function names written as camelCase
Global variables written in UPPERCASE .
Constants (like PI) written in UPPERCASE.
1.7 Statements
1.7.1 Simple Statements
Each line should contain at most one statement. Put a ; semicolon at the end of every simple statement.
Note that an assignment statement that is assigning a function literal or object literal is still an
assignment statement and must end with a semicolon.
1.7.3 Labels
Statement labels should be avoided. Only these statements should be labeled: while, do, for, switch.
1.7.5 if Statement
The if class of statements should have the following form:
if (condition) {
statements
}
if (condition) {
statements
} else {
statements
}
if (condition) {
statements
} else if (condition) {
statements
} else {
statements
}
1.7.8 do Statement
A do statement should have the following form:
do {
statements
} while (condition);
Unlike the other compound statements, the do statement always ends with a ; semicolon.
switch (expression) {
case expression:
statements
default:
statements
}
Each case is aligned with the switch. This avoids over-indentation. A case label is not a statement,
and should not be indented like one.
Each group of statements (except the default) should end with break, return, or throw. Do not fall
through.
try {
statements
} catch (variable) {
statements
}
try {
statements
} catch (variable) {
statements
} finally {
statements
}
Is
if (a = b) {
if (a == b) {
is better written as
Refernce:
https://www.nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misunderstood/
Refernce:
https://www.sitepoint.com/using-jslint-to-refine-your-code/
Code Snippet:
console.log(i);
console.log(i);
Code Snippet:
Code Snippet:
Better
var DudeNameSpace = {
name : 'Jeffrey',
lastName : 'Way',
doSomething : function() {...}
}
console.log(DudeNameSpace.name);
Notice how we've "reduced our footprint" to just the ridiculously named "DudeNameSpace" object.
Code Snippet:
// Cycle through array and echo out each name.
for(var i = 0, len = array.length; i < len; i++) {
console.log(array[i]);
}
Code Snippet:
Passing string:
setInterval(
JavaScript Best Practices
"document.getElementById('container').innerHTML += 'My new number: ' + i", 3000
);
Passing function:
setInterval(someFunction, 3000);
Reference:
https://stackoverflow.com/questions/6081560/is-there-ever-a-good-reason-to-pass-a-string-to-
settimeout
For example...
with (being.person.man.bodyparts) {
arms = true;
legs = true;
}
-- instead of --
being.person.man.bodyparts.arms = true;
being.person.man.bodyparts.legs= true;
Since With statement "behave very badly when setting new members." Instead, you should use var.
var o = being.person.man.bodyparts;
o.arms = true;
o.legs = true;
Avoid using With, as it has negatie impact on performance, as it modifies the scope chain, making it
more expensive to look up variables in other scopes.
Using with() inserts a variable at the global scope. Thus, if another variable has the same name it could
cause confusion and overwrite the value.
var a = ['Joe','Plumber'];
2.13 For Long List of Variables use Commas Omit the "Var" Keyword
Rather than declaring variables multiple time, it is better to declare one time using commas to separate
multiple variables As it cleans up code a bit.
Code Snippet:
var someItem = 'some string';
var anotherItem = 'another string';
var oneMoreItem = 'one more string';
Better
function TimeTracker(){
console.time("MyTimer");
for(x=5000; x > 0; x--){}
console.timeEnd("MyTimer");
}
Reference:
https://code.tutsplus.com/tutorials/10-reasons-why-you-should-be-using-firebug--net-5480
When looping through items in an object, you might find that you'll also retrieve method functions as
well. In order to work around this, always wrap your code in an if statement which filters the information
Usage:
for(key in object) {
if(object.hasOwnProperty(key) {
...then do something...
}
}
Reference:
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnPro
perty
2.17 Use self-executing functions to run when page loads or parent function is
called.
The main idea is that the anonymous function is being invoked right after it has been defined. The
benefit of self-invoking functions is that it enables you to execute code once without cluttering the
global namespace (without declaring any globals).
Apart from keeping the global namespace clean, they are also useful for establishing private methods
for accessible functions while still exposing some properties for later use.
counter.get(); // 0
counter.set(3);
counter.increment(); // 4
counter.increment(); // 5
Reference:
http://blog.mgechev.com/2012/08/29/self-invoking-functions-in-javascript-or-immediately-invoked-
function-expression/
https://stackoverflow.com/questions/10831724/the-purpose-of-self-invoking-anonymous-
functions?noredirect=1&lq=1
2.18 Check if Callback is defined and is executable before trying to run it.
function(callback) {
if(callback && typeof callback == 'function') callback();
};
function(callback) {
callback && typeof callback == 'function' && callback();
};
jQuery's "each" method is great for looping, but using a native "for" statement will always be an ounce
quicker.
Example:
Result:
Reference:
http://www.sebarmeli.com/blog/2010/12/06/best-way-to-loop-through-an-array-in-javascript/
https://leftshift.io/4-javascript-optimisations-you-should-know
https://www.incredible-web.com/blog/performance-of-for-loops-with-javascript/
baz.Bar = function() {
// constructor body
this.foo = function() {
// method body
};
JavaScript Best Practices
}
baz.Bar = function() {
// constructor body
};
baz.Bar.prototype.foo = function() {
// method body
};
Reference:
https://www.phpied.com/3-ways-to-define-a-javascript-class/
foo.Bar = function () {
this.prop1_ = 4;
this.prop2_ = true;
this.prop3_ = [];
this.prop4_ = 'blah';
};
Use:
foo.Bar = function () {
this.prop3_ = [];
};
foo.Bar.prototype.prop1_ = 4;
foo.Bar.prototype.prop2_ = true;
foo.Bar.prototype.prop4_ = 'blah';
JavaScript Best Practices
• Creating a closure is significantly slower than creating an inner function without a closure, and
much slower than reusing a static function. For example:
function setupAlertTimeout() {
var msg = 'Message to alert';
window.setTimeout(function () { alert(msg); }, 100);
}
is slower than:
function setupAlertTimeout() {
window.setTimeout(function () {
var msg = 'Message to alert';
alert(msg);
}, 100);
}
function alertMsg() {
var msg = 'Message to alert';
alert(msg);
}
function setupAlertTimeout() {
window.setTimeout(alertMsg, 100);
}
• They add a level to the scope chain. When the browser resolves properties, each level of the scope
chain must be checked. In the following example:
var a = 'a';
function createFunctionWithClosure() {
var b = 'b';
return function () {
var c = 'c';
a;
b;
c;
};
}
var f = createFunctionWithClosure();
f();
when f is invoked, referencing a is slower than referencing b, which is slower than referencing c.
JavaScript Best Practices
Usage:
Reference: http://skilldrick.co.uk/2011/09/understanding-typeof-instanceof-and-constructor-in-
javascript/
2.24 Don’t use delete to remove an item from array, instead use the splice.
Use splice instead of using delete to delete an item from an array. Using delete replaces the item with
undefined instead of the removing it from the array.
Instead of…
var items = [12, 548, 'a', 2, 5478, 'foo', 8852, , 'Doe', 2154, 119];
items.length; // return 11
delete items[3]; // return true
items.length; // return 11
/* items will be equal to [12, 548, "a", undefined × 1, 5478, "foo", 8852, undefined ×
1, "Doe", 2154, 119] */
Use…
var items = [12, 548, 'a', 2, 5478, 'foo', 8852, , 'Doe', 2154, 119];
items.length; // return 11
items.splice(3, 1);
items.length; // return 10
/* items will be equal to [12, 548, "a", 5478, "foo", 8852, undefined × 1, "Doe", 2154,
119] */
Truncating an array using array.length is significantly faster than the alternatives in Google Chrome
Usage:
Lets consider the example of emptying an array, we truncate it using the length property.
As a bonus, if you set the array length to a higher value, the length will be changed and new items will
be added with undefined as a value.
Reference:
https://dvolvr.davidwaterston.com/2013/06/09/restating-the-obvious-the-fastest-way-to-truncate-
an-array-in-javascript/
The logical OR could also be used to set a default value for function argument.
function doSomething(arg1) {
arg1 = arg1 || 10; // arg1 will have 10 as a default value if it’s not already set
}
JavaScript Best Practices
function getCategory(age) {
var category = "";
switch (true) {
case isNaN(age):
category = "not an age";
break;
case (age >= 50):
category = "Old";
break;
case (age <= 20):
category = "Baby";
break;
default:
category = "Young";
break;
};
return category;
}
getCategory(5); // will return "Baby"
try {
for (i = 0, len = object.length; i < len; i++) {
// do something that throws an exception
}
}
catch (e) {
// handle exception
JavaScript Best Practices
}
xhr.send();
2.30 Primitive operations can be faster than function calls. Use VanillaJS.
For example, instead of using…
…use…
MyNamespace.MyModule = function () {
// Your module is now in a namespace!
}
console.log(x);
In the code above, the first console.log() will succeed, but the second will fail. You won't be able to
reference x outside of the anonymous function.
• Events that get fired all the time (for example, resizing/scrolling)
These are problems you should address. Fixing them could result in less page stuttering.
There's one problem, though: if init() ever gets called more than once, that link is going to wind up
with handleClick() bound to it twice. And that means it'll execute twice if the link is clicked.
It's important to note that when you use jQuery event handlers, they stack. Two click() calls on the
same element will result in two function calls when the link is clicked.
In some cases, you can flat-out guarantee that your link handler won't get bound twice. In the above
example, perhaps you know for certain that init() is only called a single time, and therefore two click
handlers will never appear on your link. However, sometimes you can't be so sure, and in those
instances it's better safe than sorry.
A good defensive coding practice is to unbind an event handler before binding, like so:
It's probably a good idea to create a helper function that does the unbind()/bind() automatically,
and logs an error if the code tries to double-bind.
2.35 jQuery
2.35.1 Prefix jQuery object variables with a $.
// bad
const sidebar = $('.sidebar');
// good
const $sidebar = $('.sidebar');
// good
const $sidebarBtn = $('.sidebar-btn');
// bad
function setSidebar() {
$('.sidebar').hide();
// ...
$('.sidebar').css({
'background-color': 'pink',
});
}
// good
function setSidebar() {
const $sidebar = $('.sidebar');
$sidebar.hide();
// ...
$sidebar.css({
'background-color': 'pink',
});
}
2.35.3 For DOM queries use Cascading $('.sidebar ul') or parent > child $('.sidebar > ul').
JavaScript Best Practices
2.35.4 Use find with scoped jQuery object queries.
// bad
$('ul', '.sidebar').hide();
// bad
$('.sidebar').find('ul').hide();
// good
$('.sidebar ul').hide();
// good
$('.sidebar > ul').hide();
// good
$sidebar.find('ul').hide();
JavaScript Best Practices
Watch out for these guys. Repeated interaction with them will kill your performance.
THE PROBLEM:
Native JavaScript is compiled into machine code by most scripting engines offering incredible
performance boost, however interaction with host (browser) objects outside the javascript native
environment raises unpredictability and considerable performance lag, particularly when dealing
with screen-rendered DOM objects or objects which cause Disk I/O (such as WebSQL).
THE SOLUTION:
You can’t really get away from them, but keep your interaction with host objects to an absolute
minimum.
THE TECHNIQUES:
Its a good habit to try an implement any animation (or DOM interaction) with CSS if you can get
away with it. CSS3 Transitions have been around for a while now, so there are few excuses not to
use them. You can even use a polyfill if you are worried about older browsers. Think also of hover
menus using the :hover pseudo-class, or styling and display of elements
using @keyframes, :before and :after, this is because unlike JavaScript, CSS solutions are heavily
optimized by the browser, often down to the level of using the GPU for extra processing power.
JavaScript Best Practices
I realize this might sound like irony (if you want to optimize JavaScript – avoid using it for
animation), but the reality is that this technique is executed from within your JavaScript code, it
just involves putting more effort on the CSS classes.
Given the availability of jQuery, it is now easier than ever to produce highly specific selectors based
on a combination of tag names, classes and CSS3. You need to be aware that this approach involves
several iterations while jQuery loops thorough each subset of DOM elements and tries to find a
match. You can improve DOM traversal speeds by picking nodes by ID.
// jQuery will need to iterate many times until it finds the right element
var button = jQuery('body div.dialog > div.close-button:nth-child(2)')[0];
Use this technique to reduce DOM traversal trips by storing references to browser objects during
instantiation for later usage. For example, if you are not expecting your DOM to change you should
store a reference to DOM or jQuery objects you are going to use when your page is created; if you
are building a DOM structure such as a dialog window, make sure you store a few handy reference
to DOM objects inside it during instantiation, so you dont need to find the same DOM object over
an over again when a user clicks on something or drags the dialog window.
If you haven’t stored a reference to a DOM object, and you need to iterate inside a function, you
can create a local variable containing a reference to that DOM object, this will considerably speed
up the iteration as the local variable is stored in the most accessible part of the stack.
4. Keep your HTML super-lean (get rid of all those useless DIV and SPAN tags)
This is extremely important, the time needed to query and modify DOM is directly proportional the
the amount and complexity of HTML that needs to be rendered.
Using half the amount of HTML will roughly double the DOM speed, and since DOM creates
the greatest performance drag on any complex JavaScript app, this can produce a considerable
improvement. See ‘Reduce Number of DOM Elements’ guidance in Yahoo YSlow.
As per the last item, every DOM update requires the whole screen to be refreshed, you can
minimize the impact here by building DOM for your widget ‘off-line’ and then appending your DOM
structure in one go.
This is an extension of the fourth point above (Keep HTML super-lean), you can use this technique
to remove items from DOM that are not being visually rendered on screen, such as the area outside
the viewport of a scrollable DIV, and append the nodes again when they are needed. This will
reduce memory usage and DOM traversal speeds. Using this technique the guys at ExtJS have
managed to produce an infinitely scrollable grid that doesn’t grind the browser down to a halt.
JavaScript Best Practices
THE PROBLEM:
On-screen visual rendering and user experience is usually delayed while waiting for script
dependencies load onto the browser. This is particularly bad for mobile users who have limited
bandwidth capacity.
THE SOLUTION:
THE TECHNIQUES:
Use this approach to reduce the number of libraries your code requires to a minimum, ideally to
none, thus creating an incredible boost to the loading times required for your page.
You can reduce dependency on external libraries by making use of as much in-browser technology
as you can, for example you can use document.getElementById('nodeId') instead of jQuery('#nodeId'),
or document.getElementsByTagName('INPUT') instead of jQuery('INPUT') which will allow you to get rid of
jQuery library dependency.
If you need complex CSS selectors use Sizzle.js instead of jQuery, which is far more lightweight (4kb
instead of 80kb+).
JavaScript Best Practices
Also, before adding any new library to the codebase, evaluate whether or you really need it.
Perhaps you are just after 1 single feature in the whole library? If that’s the case then take the code
apart and add the feature separately (but don’t forget to check the license and acknowledge author
if necessary).
You can bundle distinct components of your application into combined *.js files and pass them
through a javascript minimizer tool such as Google Closures or JsMin that gets rid of comments and
whitespacing.
The logic here is that a single minimized request for a 10Kb .js file completes faster than 10 requests
for files that are 1-2kb each due to lower bandwidth usage and network latency.
Much of your functionality will not need to be implemented until after the page loads. By using a
dependency manager (such as RequireJS or Webpack) to load your scripts after the page has
completed rendering you are giving the user a few extra seconds to familiarise themselves with the
layout and options before them.
Make sure that your dependency manager can ‘remember’ which dependencies have been loaded
so you dont end up loading the same libraries twice for each module. See guidance for Pre-Loading
and Post-loading in Yahoo YSLow, and be mindful about loading only what is necessary at each
stage of the user journey.
Cache is your best friend when it comes to loading pages faster. Try to maximise the use of cache
by applying ETags liberally and putting all your javascript into files ending in *.js found in static URI
locations (avoid dynamic Java/C# bundle generations ending with *.jsp and *.ashx) . This will tell
the browser to use the locally cached copy of your scripts for any pages loaded after the initial one.
This is the lazy way of handling post-load dependencies, ideally you should implement a post-load
dependency manager, but if you only have one or two scripts to load into the page you can add
them at the very end of the HTML document where the browser will start loading them after the
page is rendered, giving the user a few extra seconds of interaction.
JavaScript Best Practices
THE PROBLEM:
Browser and custom event handlers are an incredible tool for improving user experience and
reducing the depth of the call stack (so you avoid having a function calling a function which calls
another function etc), but since they are hard to track due to their ‘hidden’ execution they can fire
many times repeatedly and quickly get out of hand, causing performance degradation.
THE SOLUTION:
Be mindful and disciplined when creating event handlers. Get to know your weapons too, if you are
using a framework then find out what’s going on underneath the hood.
THE TECHNIQUES:
Event binding is great for creating responsive applications. However, it is important that you walk
through the execution and various user journeys to make sure they are not firing multiple times or
using up unnecessary resources behind the scenes. Comment your code well so they next guy
(which may be you a few months down the line) can follow what’s going on and avoid this issue as
well.
If you are using AngularJS make sure you are getting rid of unnecessary ‘watchers’. These are
background events that involve heavy processing and will slow down your app, particularly on
mobile devices.
JavaScript Best Practices
2. Pay special attention event handlers that fire in quick succession (ie, ‘mousemove’).
Browser events such as ‘mousemove’ and ‘resize’ are executed in quick succession up to several
hundred times each second, this means that you need to ensure that an event handler bound to
either of these events is coded optimally and can complete in less than 2-3 milliseconds.
Any overhead greater than that will create a patchy user experience, specially in browsers such as
IE that have poor rendering capabilities.
Unbinding events is almost as important as binding them. When you add a new event handler to
your code make sure that you provide for it to stop firing when it is no longer needed, ideally using
once-off execution constructs like jQuery.one() or coding in the unbind behaviour at that point. This
will avoid you having the same handler bound multiple times degrading performance, or events
firing when they are no longer needed, this often points to memory leaks in your app as pointed
out by the React developers in this blog post.
If you are using jQuery to bind and unbind events, make sure your selector points to a unique node,
as a loose selector can create or remove more handlers than you intend to.
If you are going to use event handlers, it is important that you understand how event bubbling
propagates an event up the DOM tree to every ancestor node. You can use this knowledge to limit
your dependency on event bubbling with approaches such as jQuery.live() and jQuery.delegate()
that require full DOM traversal upon handling each event, or to stop event bubbling for improved
performance. See this great post on the subject.
Remember that user interaction via the mouse or keyboard fires several events in a specific order.
It is useful to remember the order in which these events fire so you can squeeze in your
functionality before anything else gets handled, including native browser event handlers.
A good example of this is to bind your functionality to the ‘mouseup’ event which fires before the
‘click’ event, this can produce a surprising performance boost in older browsers such as IE, making
the difference between handling every interaction or missing some of the action if the user triggers
clicks many times in succession.
JavaScript Best Practices
THE PROBLEM:
Due to the processing time used, iterations are usually the first places where you can address
performance flaws in an application.
THE SOLUTION:
THE TECHNIQUES:
Native JavaScript objects {} can be used as powerful Hashtable data structures with quick-lookup
indexes to store references to other objects, acting similarly to the way database indexes work for
speeding up search operations by preventing needless looping.
So why bother iterating to find something? You can simply use a plain object as an index (think of
a phone-book) to get to your desired item quickly and efficiently. Here is an example as follows:
var data = {
index: {
"joeb": {name: "joe", surname: "bloggs", age: 29 },
"marys": {name: "mary", surname: "smith", age: 25 }
// another 1000 records
},
get: function(username) {
return this.index[username];
}
JavaScript Best Practices
}
2. Harness the power of array structures with push() and pop() and shift().
Array push() pop() and shift() instructions have minimal processing overhead (20x that of object
manipulation) due to being language constructs closely related to their low-level assembly language
counterparts. In addition, using queue and stack data structures can help simplify your code logic
and get rid of unnecessarily loops. See more on the topic in this article.
JavaScript, much like other C-based languages, has both primitive and reference value types.
Primitive types such as strings, booleans and integers are copied whenever they are passed into a
new function, however reference types such as arrays, objects and dates are passed only as a light-
weight reference.You can use this to get the most performance out of recursive functions, such as
by passing a DOM node reference recursively to minimise DOM traversal, or by passing a reference
parameter into a function that executes within an iteration. Also, remember that comparing object
references is far more efficient than comparing strings.
PLEASE NOTE: This article was first written in 2012 when string concatenation was a hazard to be
aware of. However, these days most JavaScript engines have compilation tricks that have made this
issue obsolete. The wording below is only really relevant for historical purposes.
Joining strings using the plus sign (ie var ab = 'a' + 'b';) creates performance issues in IE when used
within an iteration. This is because, like Java and C#, JavaScript uses unmutable strings.
Basically, when you concatenate two strings, a third string is constructed for gathering the results
with its own object instantiation logic and memory allocation. While other browsers have various
compilation tricks around this, IE is particularly bad at it.A far better approach is to use an array for
carrying out the donkey work, creating an array outside the loop, using push() to add items into to
the array and then a join() to output the results. See this link for a more in-depth article on the
subject.
JavaScript Best Practices
Become a friend of the ECMA Standard and it make your code faster.
THE PROBLEM:
Due to its loosely-typed and free-for-all nature, JavaScript can be written using a very limited subset
of lexical constructs with no discipline or controls applied to its use. Using simple function patterns
repetitively often leads to poorly thought-out ‘spaghetti’ code that is inefficient in terms of resource
use.
THE SOLUTION:
Learn when and how to apply the constructs of the ECMAScript language standard to maximise
performance.
THE TECHNIQUES:
In JavaScript, whenever a function is executed, a set of first order variables are instantiated as part
of that function. These include the immediate scope of a function (the this variable) with its own
scope chain, the arguments of the function and all locally-declared variables.
If you try and access a globally-declared variable or a closure further up the scope chain, it will take
extra effort to traverse up the chain every level util the compiler can wire up the variable you are
after. You can thus improve execution by reducing the depth of the call stack, and by only using the
JavaScript Best Practices
local scope (this), the arguments of the function, as well as locally declared variables. This
article explains the matter further.
2. Make use of ‘this’, by passing correct scope using ‘call’ and ‘apply’.
This is particularly useful for writing asynchronous code using callbacks, however it also improves
performance because you are not relying on global or closure variables held further up the scope
chain. You can get the most out of the scope variable (this) by rewiring it using the special call() and
apply() methods that are built into each function. See the example below:
ECMAScript provides a whole host of native constructs that save you having to write your own
algorithms or rely on host objects. Some examples include Math.floor(), Math.round(), (new
Date()).getTime() for timestamps, String.prototype.match() and String.prototype.replace() for
regexes, parseInt(n, radix) for changing numeral systems, === instead of == for faster type-based
comparsion, instanceof for checking type up the hierarchy, & and | for bitwise comparisons. And the
list goes on and on.
Make sure you use all these instead of trying to work out your own algorithms as you will not only
be reinventing the wheel but affecting performance.
This is because ‘switch’ statements can be optimized more easily during compilation. There is an
interesting article in O’Reily about using this approach with JavaScript.