Javascript Coding Standards

Basics

Potential Bugs

Always use the “var” keyword when declaring a variable. Not doing so is not only bad form, but can also cause nasty bugs and pollute global scope.

window.widget = { name: "whatsit" };

(function() {
     // Setting the value of widget will affect global scope when creating a local variable is intended
     window.foo = function foo() {
          widget = true;

          // other stuff
     }
})();

window.foo();

alert(window.widget.name); // Undefined, since value was changed inadvertantely

Always use a semi-colon at the end of a statement. The browser may tack it on for you, but it will cause bugs when minified.

This also applies to a function assigned to a variable. Otherwise, the semi-colon is not necessary.
// Use semi-colon
var fn = function() {
     // do something...
};

// Don't use semi-colon
function foo(){
     // do something...
}

Don’t use trailing commas in object or array initializers. Some browsers may ignore them, but some may not.

// Some browsers will choke on the trailing comma
var foo = {
     A: true,
     B: false,
     C: true,
};

Programming Style

Always use {} for blocks, even when only one line

// This is preferred...
if (condition) {
     doSomething();
}

// Instead of this...
if (condition)
     doSomething();

Declare variables before used and ideally nearby usage. If many variables are declared near usage and are not at the beginning of the function, then the function might be doing too much. Declare each variable on a separate line.

function last(arr) {
     var text = arr[arr.length - 1];
     var index = text.length - 1;

     return text[index];
}

Where appropriate, add variable comments at the end of the line.

var lastUpdate;  // this value is referenced and updated each time something happens

Use descriptive name with as little abbreviation as possible while keeping short. Use camel case for variable names. If the name is 10 or more characters long, you should begin to consider abbreviation. Use comments if necessary to ensure that its purpose is clear.

// short name, not abbreviated
var index = 0;  // comments go here if necessary...

// too much abbreviation, name is not clear
var lclFnLpIdx = 5;

// longer name, abbreviation optional but prefer none
var localIndex = 0;
var localIdx = 0;

// longer name, some abbreviation
var fakeObjFactory = {};
var fakeObjFact = {};
var fakeObjectFact = {};

// name is too long
var myCustomArrayWithAdditionalInfo = [];

Try to keep function logic as small and isolated as possible. Reuse with functions rather than copy-paste.

Example:
// From this...
//-------------------------
MyClass.prototype = {
     // ...

     foo: function() {
          // operation 1
          // operation 2
          // special-case
          // operation 3
     },
     bar: function() {
          // operation 1
          // special-case
          // operation 2
          // operation 3
     }

     // ...
};

// To this...
//-------------------------
function op1() {

}

function op2() {

}

function op3() {

}

MyClass.prototype = {
     // ...

     foo: function() {
          op1();
          op2();
          // special-case
          op3();
     },
     bar: function() {
          op1();
          // special-case
          op2();
          op3();
     },

     // ...
};

Return early for exit conditions rather than nested if statements. This reduces nesting, and makes exit conditions isolated and more clear.

// "if" conditions should be written as exit conditions
//----------------------------
if (bool1 && bool2 && (bool3 || fn(some_value) && ...) {
     // do some stuff
}

// Preferred alternative
//----------------------------
// explanation...
if (!bool1){
     return;
}

// explanation...
if (!bool2) {
     return;
}

// explanation
if (!bool3 && !fn(some_value)) {
     return;
}

// do some stuff

Always be aware of the lack of block scope and its implications.

  • A loop will not maintain distinct values for each iteration.
// The variable i will contain its LAST value when the function 
// is called, which is probably not correct.
for (var i = 0; i < len; i++) {
     wait(function() {
          // do something with the value of "i"
     });
}
  • Don't declare variables within a block and use them elsewhere. This can be confusing.
if (some_value) {
     var val = 1;
}

val += 1000;

Avoid assignment in logical expressions such as "if" and "while" since this can be confusing.

var obj;
if ((obj = getObj()).selected === true) {
     // do something
}

Avoid use of “continue”, “with”, “eval".

var obj = {
     foo: 5
     //bar: null
};

with(obj) {
     foo = 7;
     bar = "test";
}

console.log(obj.bar);  // undefined
console.log(window.bar); // test

Comment the why, not the how!

Write comments as if you were trying to explain to your future self why the code is doing what it does. Avoid silly comments that simply translate the code into natural language or layman's terms.

Use “===” and “!==” to test for equality unless coercion is desired. In most cases it is not.

if (myVar === true) {

}

Cosmetics

Lines should not contain trailing spaces or tabs for any reason.

I don't think an example is really necessary here :)

Prefer double quotes over single quotes to maintain consistency.

// Prefer this...
var key = "adio3s9";

// Instead of this...
var key = 'adio3s9';

Avoid long lines of code. The convention is some languages is 80 characters, but we will not impose an exact limit.

  • If a line must be split up, break after an operator with no white-space after.
  • Following lines should be indented additionally by one unit (whether it be tab or a number of spaces).

No spaces between function name (or “function” keyword) and parenthesis

// Prefer this...
function foo() {

}

// Instead of this...
function foo () {

}

One space between closing parenthesis and opening bracket of a function declaration.

// Prefer this...
function foo() {

}

// Instead of this...
function foo(){

}

No spaces between parentheses and argument names.

// Prefer this...
function foo(arg1) {

}

// Instead of this...
function foo( arg1 ) {

}

No extra spaces in object initializer {} or array initializer [].

// Prefer this...
var obj = {};

// Instead of this...
var obj = { };

Use open bracket on the same line as the function label, no need for an extra line.

// Don't do this
function foo()
{

}

// Do this instead
function foo() {

}

Begin else case on its own line.

// Don't do this
if (true) {

} else {

}

// Do this instead
if (true) {

}
else {

}

Tabs are discouraged in multiple sources but we use them, so use tabs to maintain consistency.

Edit: jquery uses tab. +1

Sources referenced:

http://javascript.crockford.com/code.html
http://docs.jquery.com/JQuery_Core_Style_Guidelines

Other sources to consider:

http://o.dojotoolkit.org/developer/StyleGuide
http://code.google.com/p/gmaps-utility-library-dev/wiki/JavascriptCodingConventions
http://www.asp.net/ajaxlibrary/act_contribute_codingStandards.ashx
https://developer.mozilla.org/en/JavaScript_style_guide
http://www.slideshare.net/cheilmann/fronteers-maintainability-presentation
http://ajaxian.com/archives/maintainable-javascript-videos-are-now-available

Last edited Jul 31, 2010 at 4:51 PM by mattheyan, version 21

Comments

No comments yet.