Each language has a way of doing the right things and doing things right; and JavaScript is no exception
The main trick with JavaScript is to avoid taking the easy path.
JavaScript is a versatile “language” and as the environment it is executed in is very forgiving, it is easy to write sloppy code that seemingly does the job.
This same code however will come back to bite you a few months down the line
I’d like to share a list of best practices in JavaScript development, that I’ve habitualized over time.
Following them not only makes your code more robust and less error prone; but it will make your application more responsive, faster and less resource-intensive.
Don’t Pollute the Global Namespace
Put all of your variables into closures and show love to the module pattern
Take a look at YUI, for instance. It’s a huge codebase with only 2 global objects: YAHOO and YAHOO_config.
As a side-note, don’t forget to var your variables:
Variables in JavaScript either have global scope or function scope, and using the ‘var’ keyword is vital to keeping them straight. When declaring a variable for use either as a global variable or as a function-level variable, always prefix the declaration with the ‘var’ keyword.
Write Reusable Code
As you develop your codebase, you’ll see useful bits of code that can be used by other parts of your code. When you see such a code, factor it out in a module, enhance it and make it re-usable.
While writing your code always keep reusability in mind
Minimize JavaScript/DOM Interaction
Accessing the DOM in browsers is an expensive thing to do. The DOM is a very complex API and rendering in browsers can take up a lot of time. You can see this when running complex web applications when your computer is already busy with other work — changes take longer.
Going back and forth between the JavaScript domain and the browser’s DOM is both resource-consuming and may lead to memory leaks if not managed correctly.
Therefore, minimize JavaScript/DOM interaction as much as possible. For instance if you are going to add a bunch of nodes to DOM, create a DocumentFragment, add those nodes offline to this fragment and then append that fragment to DOM, instead of adding each of the node to DOM one by one.
Besides, if you need to save state, it’s probably best to use objects instead of the DOM.
To make sure that your code is fast and doesn’t slow down the browser to a halt try to keep DOM access to a bare minimum. For instance, instead of constantly creating and applying DOM nodes, have a tool function that turns a string into DOM elements and call this function at the end of your generation process to disturb the browser rendering once rather than continually.
Note that, DOM Depth and Total DOM Node Count are equally important for performance. To have a fast-performing web application, minimize your DOM size and DOM Nesting Depth as much as possible.
Use Object Detection
Avoid code written to detect browser versions and take a different action base on the user agent. This, in general, is a very bad practice. Any code which even looks at the global “navigator” object is suspect.
Come on… we are in the year 2011, do I still need to remind this
?
The better approach is to use feature detection. That is, before using any advanced feature that an older browser may not support, check to see if the function or property exists first, then use it.
eval is “evil”
In almost all cases, eval should never be used. If it exists in your page, there is almost always a more correct way to accomplish what you are doing.
The eval function in is a way to run arbitrary code at run-time. Since any code can run through eval, it can introduce a great security risk!
99.99% of the time you won’t need eval. I haven’t used it for more than 4 years, I guess ![]()
The rule of thumb is, “Eval is evil!”. Don’t use it unless you are an experienced developer and know that your case is one of those %.01 exceptional cases.
Passing a string to setTimeout or setInterval, or passing a string to Function constructor is equally evil. Avoid these at all costs.
Avoid the with Statment
The ‘with’ statement in javascript inserts an object at the front scope chain, so any property/variable references will first try to be resolved against the object. This makes your code run slower, and makes it unreadable and unmaintainable.
//avoid this
with (document.forms["mainForm"].elements) {
input1.value = "junk";
input2.value = "junk";
}
//do this instead
var elements = document.forms["mainForm"].elements;
elements.input1.value = "junk";
elements.input2.value = "junk";
Always Sanitize Your Data
If you know that your data is a number, than cast it to a number. If you know that it represents a Date, then convert it to a Date object.
//age is a String.
var age = document.getElementById('age').value;
//sanitize your data
age = (+age);//the unary operator will convert age to a number.
//or
age = parseInt(age, 10);
A very insecure practice is to read information from the DOM and use it without comparison.
One of the main points to bear in mind when talking about code and data security is not to trust any data. This is not only about evil people wanting to hack your systems; it starts with plain usability:
Users will enter incorrect data, all the time. Not because they are stupid, but because they are busy, distracted or the wording on your instructions is confusing them.
In short, make sure that all the data that goes into your systems is clean and exactly what you need.
Avoid Sync AJAX
If you think that your situation requires sync mode, it is most likely time to re-align your design. Very few (if any) situations actually require AJAX requests in sync mode.
JavaScript is single-threaded by nature. Therefore, issuing a synchronous AJAX call will block the entire GUI until the AJAX call’s response ends. This is a very bad usability practice. And it can be really disturbing for the end-user.
In cases where the server is busy and the response takes a while, the user’s browser (and maybe OS) will not allow anything else to be done. In cases where a response is never properly received, the browser may continue to block until the request is timed out.
JSON is Your Friend
When storing data structures as plain text or sending/retrieving data structures via AJAX, use JSON instead of XML or plain HTML, when possible. JSON is a more compact and efficient data format, and is language-neutral.
Use Long, Understandable Variable Names
See your code as a narrative. If you can read line by line and understand what is going on, well done. If you need to use a sketchpad to keep up with the flow of logic, then your code needs some work. Try reading Dostojewski if you want a comparison to the real world
![]()
This is a no-brainer but it is scary how often you will come across variables like x1, fe2 or xbqne in JavaScript and in many other languages per se.
On the other end of the spectrum, variable names like “loopFlagThatMasterProcedureIsLockedOnWhenDomIsReady” are equally ridiculous.
A good variable and function names should be
- easy to understand
- explain you what it is meant for
Nothing more, and nothing less
One trap to avoid is mixing values and functionality in names. A function called isLegalDrinkingAge() makes more sense than isOverEighteen() as the legal drinking age varies from country to country.
Stick to a Strict Coding Style
Browsers are very forgiving when it comes to JavaScript syntax. This should not however be a reason for you to write sloppy code that relies on browsers to make it work.
JSLint is a debugger written by Douglas Crockford. Simply paste in your script, and it’ll quickly scan for any noticeable issues and errors in your code. Before signing off on a script, run it through JSLint just to be sure that you haven’t made any mindless mistakes.
Clean and valid code means less confusing bugs to fix, easier handover to other developers and better code security.
Valid code also means that it can be converted by scripts to other formats.
Comment Your Code
Comments are your messages to other developers (and yourself, if you come back to your code after several months working on something else).
There’s been numerous battles raging over the years about whether to use comments at all, the main argument being that good code should explain itself. What I see as a flaw in this argument is that explanations are a very subjective thing — you cannot expect every developer to understand what some code is doing from exactly the same explanation.
Comments don’t hurt anybody if you do them right
For larger applications comment documentation in JS-Doc style. The Yahoo User Interface library’s success is partly attributable to this.
Show Love to the Object Literal
Instead of this:
var cow = new Object();
cow.color = 'brown';
cow.moo = function(){ console.log('moo'); }
cow.feetCount = 4;
cow.isNinja = false;
Do this:
var cow = {
color:'brown',
moo:function(){ console.log('moo);},
feetCount:4,
isNinja: false
};
Shorten Conditions using Ternary Notation
Instead of this:
var direction;
if(x > 100){ direction = 1;
} else { direction = -1; }
Do this:
var direction = (x > 100) ? 1 : -1;
Use Default (||) and Guard (&&) Operators
//if v is truthy, sets x to v. otherwise defaults x to 10: var x = v || 10; //initializes x to ninja.name, only if ninja is available: var x = ninja && ninja.name;
Each Method Should do One Task
And each method shoud do that task good.
Making sure that you create functions that fulfill one job at a time makes it easy for other developers to debug and change your code without having to scan through all the code to work out what code block performs what function.
This also applies to creating helper functions for common tasks. If you find yourself doing the same thing in several different functions then it is a good idea to create a more generic helper function instead, and reuse that functionality where it is needed.
Allow for Configuration and Localization
If things are not obvious, your solution will be either completely ditched or hacked. Hacked solutions can’t be patched once you need to upgrade them and that kills code re-use.
One of the most successful tips to keep your code maintainable and clean is to create a configuration object that contains all the things that are likely to change over time. These include any text used in elements you create (including button values and alternative text for images), CSS class and ID names and general parameters of the interface you build.
See the config section of o2.Debugger, for example:
/**
* Module configuration.
*/
var config = {
/**
* {DOMNode} outputElement - A readonly property indicating
* the node to output the Debugger outcomes.
* This value will be set after o2.Debugger.init method is called.
*/
outputElement: null,
/**
* {Boolean} isUsingConsole - A reaodonly property.
* If true browser's builting debug console is utilized.
* This value will be set after o2.Debugger.init method is called.
*/
isUsingConsole: true,
/**
* {Boolean} isInitialized - A readonly property.
* If true, o2.Debugger has been successfully initialized.
* If false o2.Debugger is not initialized yet.
* This value will be set after o2.Debugger.init method is called.
*/
isInitialized: false,
constants : {
className: {
/** @constant */
FAIL: 'fail',
/** @constant */
PASS: 'pass',
/** @constant */
ERROR: 'error',
/** @constant */
LOG: 'log'
},
text: {
/** @constant */
PASS: '<b>PASS:</b> ',
/** @constant */
FAIL: '<b>FAIL:</b> ',
/** @constant */
ERROR: '<b>ERROR:</b> '
}
}
};
Neat, right?
If you have this as a part of a module pattern and make it public, you even allow implementers to only override what they need before initializing your module.
It is of utmost importance to keep code maintenance simple, avoiding the need for future maintainers having to read all your code and find where they need to change things.
Embrace Braces
Always use braces. To avoid pitfalls like this:
//this code may not behave as expected.
if(someVariableExists)
x = false;
anotherFunctionCall();
//while the actually intended code might be this:
if(someVariableExists) {
x = false;
anotherFunctionCall();
}
Always use Semicolons
It’s also a good practice to always use semicolons, to avoid JavaScript engine’s guesswork.
if(someCondition)
return
{width:100;height:100}
will be interpreted by the JavaScript engine as:
if(someCondition){
return;//returns undefined.
}
//the code will not reach here
{width:100;height:100};
Where the intended use is actually:
if(someCondition) {
return {width:100;height:100};
}
StyleSheets to the Top, Scripts to the Bottom
Move style sheet links to the top of your page, and script links to the bottom of your page (We’ll be talking about this more in the upcoming discussions.).
Remember — the primary goal is to make the page load as quickly as possible for the user. When loading a script, the browser can’t continue on until the entire file has been loaded. Thus, the user will have to wait longer before noticing any progress.
If you have JavaScript files whose only purpose is to add functionality — for example, after a button is clicked — go ahead and place those files at the bottom, just before the closing body tag.
Minimize Scope and Namespace Lookups
- Cache commonly-used global variables and functions in the local scope
- Minimize namespace lookup (i.e. try to derease the number of dots used in the code
These can be better explained with an example:
Instead of this:
for(var i = 0; i < someArray.length; i++) {
var container = document.getElementById('container');
container.innerHtml += 'my number: ' + i;
some.big.namespace.modify(container);
}
Do this:
//cache the globally used function.
var modify = some.big.namespace.modify;
//cache the commonly used varaiable
var container = document.getElementById('container');
//calculate the length only once.
for(var i = 0; len = someArray.length; i < len; i++) {
container.innerHtml += 'my number: ' + i;
modify(container);
}
Use Arrays for String Concatenation
Using an Array to build up strings instead of using the + operator has significant performance gains:
var arr = ['item 1', 'item 2', 'item 3', ...];
var list = ['<ul><li>', arr.join('</li><li>') , '</li></ul>'].slice('');
Use [] instead of new Array(), use {} instead of new Object()
var ar = [];
var obj = {};
that simple
Use hasOwnProperty when looping with a for-in Statement
for(key in object) {
if(object.hasOwnProperty(key) {
...then do something...
}
}
Native JavaScript is Faster
JavaScript libraries, such as jQuery and Mootools, can save you an enormous amount of time when coding — especially with AJAX operations.
Having said that, always keep in mind that a library can never be as fast as raw JavaScript (assuming you code correctly).
For example, jQuery’s “each” method is great for looping, but using a native “for” statement will always be quicker.
Keep in Mind that undefined can be Overwritten
undefined is a type with exactly one value: “undefined”.
The language also defines a global variable that has the value of “undefined”, this variable is also called undefined. But this variable is not a constant, nor is it a keyword of the language. This means that its value can be easily overwritten.
In order to protect code against a possible overwritten undefined variable, a common technique used is to add an additional parameter to an anonymous wrapper, that gets no argument passed to it.
var undefined = 123;
(function(something, foo, undefined) {
// undefined in the local scope is retained.
})('Hello World', 42);
Lazy Load JavaScript, when Possible
If you have a large library or set of libraries you don’t need to load everything when a page is
loaded. Load the part you’ll need later on dynamically at runtime (we’ll come to that in a later tutorial).
Separate Content, Presentation and Behavior
Which means separate the HTML, CSS, and JavaScript apart from each other.
Separating the CSS styles from the JavaScript is a practice which will make your code more manageable, easier to read, and easier to customize.
Don’t use inline CSS or inline JavaScript in your HTML files.
Don’t create style attributes with JavaScript, use classNames instead.
Decouple JavaScript, CSS, and HTML as much as you can.
…
That’s all that come to my mind ![]()
I’m sure you have other things to add.
Feel free to share your comments.

