(My) JavaScript Coding Guidelines and Standards

Preface

These JavaScript guidelines are based on usage with the Yahoo! User Interface Libary (YUI). Most of the stuff mentioned can also be applied with no regards which library you use (or if you don’t use one at all). As a general rule, I try to run my JavaScript code through JSLint and most of the following guidelines are based on and often reference Douglas Crockford’s Code Conventions for the JavaScript Programming Language.

Module Declaration

Each JavaScript feature/module should be coded according to a proper JavaScript Programming Pattern, preferably the Revealing Module Pattern. This keeps your JavaScript safe from namespace collisions and also means you can expose only a limited “public” interface whilst keeping the unsightly workings of your module hidden away in a closure. Naming of the module should follow the YAHOO.YourNameSpace.yourFunction convention. I have chosen “CRUSH” as my namespace, so the declaration of someFunction could be like:

YAHOO.CRUSH.someFunction = function() {} ();

Using YUI Methods

I try to use YUI methods over their native equivalents e.g. Use YAHOO.util.Dom.get() instead of document.getElementById(). The YUI equivilents tend to normalise buggy browser behaviour.

To reduce lookup times, use code similar to the following to reduce lookup times to YUI modules:

// shortcuts to modules
var YDOM = YAHOO.util.Dom;
var YEvent = YAHOO.util.Event;
var YConnect = YAHOO.util.Connect;

Indentation

JavaScript code should be indented by 4 spaces.

  • In vi, the setting is: :set shiftwidth=4 tabstop=4 softtabstop=4 expandtab

Programming Constructs

Variables

  • Always declare private vars with var
  • All variables should be declared before used
  • The var statements should be the first statements in the function body

These can be – again – found in Douglas Crockford’s standards.

It is preferred that each variable be given its own line and comment.

var currentEntry; // currently selected table entry
var level;        // indentation level
var size;         // size of table

The new operator

Only use the new operator when calling a constructor function to instantiate a new object. It is unnecessary to use the new operator in all other instances, for example to create new arrays, objects, numbers, strings or boolean:

var names = [];   // creates a new array, no need to use new Array()
var tokenizer = {};   // creates new object, no need to do new Object()
var average = 2;   // creates new number, no need to use new Number()
var message = "An error has occurred!";   // creates a new string, no need to use new String()
var hasChildren = true;   // creates new boolean, no need to use new Boolean()

As stated by Crockford: Do not use new Function to create function values. Use function expressions instead.

Functions

“Every function should only do one thing“. What this basically means is that you should aim towards keeping your functions as small as possible and rather have 3 different functions with smaller chunks of code than 1 big function. Having smaller chunks enhances readability of your code and makes it more maintainable. A good indicator of whether the function should be split up is the name of the function. If the function actually does more than the name of the function implies, then it sounds like the function should be split up into 2 or more functions.

Statements

Each line should contain at most one statement

Curly Braces should open on the same line and close at the same indent. Example:

if (tags) {
   // fill array
} else {
   // display error
}

When looping through objects using for (variable in object), use the singular for of the object for naming, example:

for (var person in people) {
    // do something with that Person array
}

When looping through arrays, use a fast method for iterating over the elements in the array, e.g.

var arr = [1,2,3,4,5];
for (var i = 0, len = arr.length; i < len; i++) {
  alert(arr[i]);
}

For all other statements, refer to Douglas Crockford’s Coding Standards.

Comments and Documentation

The YUI team uses a syntax for their comments and documentation similar to Javadoc, see e.g. YAHOO.js. I consider this quite good practice cause it forces the developer to note what each function does and gives you a way of creating a bundled up documentation at some later point.

Line Comments

Use inline comments for explaining what a variable is used for:

var getStyle; // for load time browser branching

Taken from Douglas Crockford: Make comments meaningful. Focus on what is not immediately visible. Don’t waste the reader’s time with stuff like

i = 0; // Set i to zero.

Marking Code fragments as HACK or TODO

There will be instances in JavaScript when you, as the developer, must put in some code to hack around a specific browser bug. When doing so, mark this code fragment like:

/*
 * HACK: The following code works around the [insert bug name here] bug in IE6
 * ...short explanation what it does...
 */
...your code goes here...

If there is some stuff that due to several reasons was not tackled when the module was initially developed, mark that section like:

/*
 * TODO: This section is a bit bloated and should use YUI methods instead of DOM methods
 * Should also use switch instead of if...else
 */
...your code goes here...

Block Comments

Modules

For your module that you have created, define comments like this just before the module declaration.

/**
 * Provides helper methods for DOM elements.
 * @author Klaus Komenda <komenda@yahoo-inc.com>
 * @namespace YAHOO.util
 * @class Dom
 */
 YAHOO.util.Dom = { 
 ...
  • First line: should describe what the module does, e.g. “Provides helper methods for DOM elements.”
  • @author (required): Name of the author and the email address
  • @namespace (required): states the namespace under which this module is created, e.g. “YAHOO.util”
  • @class (required): is the name of the module, e.g. “Dom”

Functions

When documenting a function within your module, do it like this:

/**
 * Inserts the new node as the previous sibling of the reference node 
 * @method insertBefore
 * @param {String | HTMLElement} newNode The node to be inserted
 * @param {String | HTMLElement} referenceNode The node to insert the new node before 
 * @return {HTMLElement} The node that was inserted (or null if insert fails) 
 */
insertBefore: function(newNode, referenceNode) {
    ...
}
  • First line: should describe what the function does, e.g. “Inserts the new node as the previous sibling of the reference node.”
  • @method (required): is the name of the function, e.g. “insertBefore”
  • @param (optional): if the function accepts one or more parameters, they should be listed here, one parameter per line, e.g. “{String | HTMLElement} newNode The node to be inserted”
  • @return (optional): if the function returns something, list the type of that variable plus a description, e.g. “{HTMLElement} The node that was inserted (or null if insert fails)”
Conventions for @param and @return

When listing a parameter using @param, it should follow the following convention

@param {[allowed types, separated by | ]} [param name as defined in the function] [param description]

So if the parameter can only be of one specific type, state it like this:

@param {String} property The style property to be set.

When the parameter accepts multiple types, use:

@param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements

Allowed types for variable types:

  • String
  • HTMLElement
  • HTMLDocument
  • Event
  • Array
  • Int
  • Boolean
  • Region
  • Function
  • Object

Miscellaneous

Single Quotes vs. Double Quotes

Use single quotes or double quotes, but don’t mix them. They should be consistent across your code.

Accessing attributes of HTML elements

To access a property of a DOM object, always use Object.property. Avoid using .getAttribute and .setAttribute

JSLint

JSLint is a tool by Douglas Crockford that checks your JavaScript code against his code conventions (which are the basis for my code standards on this page). I think having such a tool is as great as it is to have standards. So I recommend using it, although “I have to warn you, JSLint will hurt your feelings” as Douglas would point out during his presentations. I personally turn on (check) the following JSLint options:

  • Strict whitespace
  • Assume a browser
  • Disallow undefined variables
  • Disallow == and !=

Example Code

<script type="text/javascript" src="http://yui.yahooapis.com/2.5.1/build/yahoo-dom-event/yahoo-dom-event.js"></script> 
<script type="text/javascript">
YAHOO.namespace("CRUSH");

/**
 * YAHOO.CRUSH.Toons alerts the name of a Toon character
 * @author Firstname Lastname <example@example.com>
 * @namespace YAHOO.CRUSH
 * @class Toons
 */
YAHOO.CRUSH.Toons = function () {
    var toons; // holds ID, firstname and lastname

    toons = {
        101: ["Mickey", "Mouse"],
        102: ["Donald", "Duck"],
        103: ["Bugs", "Bunny"],
        104: ["Daffy", "Duck"]
    };

    /**
     * Returns full name of Toon character
     * @method getFullNameById
     * @param {Integer} id UserID of the Toon
     * @return {String} fullname of the Toon
     */
    var getFullNameById = function (id) {
        var fullName = toons[id][0] + " " + toons[id][1];
        return fullName;
    };

    return {
        /**
         * Alerts name of Toon
         * @method init
         * @param {Integer} id UserID of the Toon
         */
        init: function (id) {
            var user = getFullNameById(id);
            alert(user);
        }
    };
}();

YAHOO.CRUSH.Toons.init(102);
</script>

Further reading

About the author

This website is the personal web appearance of Klaus Komenda, an Austrian web developer. The about section offers more info about me and this site.

Categories

Copyright © 2000-2014 Klaus Komenda

Switch to our mobile site