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.
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() {} ();
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;
JavaScript code should be indented by 4 spaces.
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
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.
“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.
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,j=arr.length; i<j; i++) {
alert(arr[i]);
}
For all other statements, refer to Douglas Crockford’s Coding Standards.
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.
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.
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...
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 = {
...
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) {
...
}
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:
Use single quotes or double quotes, but don’t mix them. They should be consistent across your code.
To access a property of a DOM object, always use Object.property. Avoid using .getAttribute and .setAttribute
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:
<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>
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.