Summary of the Javascript Coding Guidelines - ΩJr. Coding Guidelines

This information lives on a webpage hosted at the following web address: 'https://www.omegajunior.net/code/guidelines/'.

Javascript Coding Guidelines are intended to make it easier to read our work, both for colleagues when we are away, and for ourselves in a year’s time. The Guidelines also answer newbie questions, in order to reduce the learning curve.

You will notice a single theme throughout all the guidelines: readability. Increasing that should lead to a decrease in errors, easier maintenance and testing, and a less arduous transfer to coworkers.

This is the summary. It omits explanations. It contains the guidelines and the examples. For explanations, visit the annotated version.

Suggestions are welcome.

A word from a sponsor:


Know your Javascript

Javascript Basics, from the Web Standards Curriculum.


Avoid depending on javascript for critical functionality

When data comes back from the user, or when the user starts up instructions that lead to critical changes, always double-check it by a secondary, tamper-resistant method.


Get along nicely




Using Strict Mode

function hello(what) {
"use strict";
window.alert("hello, " + what);
}



Feature Detection

Bad:
if (/MSIE/.test(window.navigator.userAgent)) {
window.attachEvent(window, "load", someFunction);
}


Good:
if ((typeof window != "undefined") && (typeof someFunction != "undefined")) {
if (typeof window.alert != "undefined") {
if (typeof window.addEventListener != "undefined") {
window.addEventListener("load", someFunction, false);
}
else if (typeof window.attachEvent != "undefined") {
window.attachEvent("onload", someFunction);
}
else {
window.alert("What browser are you using?");
}
}
}

Alright. Don’t write the above: use a cross-browser library like jQuery instead. But you get the idea.


About cross-browser libraries

Use them when needed.


Adding Javascript to your web pages

<script type="text/javascript" id="myGenericProgram" src="myScript.js?20111115T1703"></script>
<script type="text/javascript" id="mySpecificProgram">/* <![CDATA[ */
var my = ({});
/* ]]> */</script>



Use consistent indentation

We use indentation to recognise where block statements start and stop. Use the Drupal Javascript Coding Standards for hints about white space, brace style, and indentation. A summary:

All examples on this page comply to this guideline.


Use a namespace

Bad:
var _gac = (_gac || []);
function doSomething() {
return _gac;
}


Better:
var my = ({});

my._gac = (_gac || []);

my.doSomething = function () {
return my._gac;
}




Declare your variables

Declaring happens with the “var” keyword at the statement start.
var price = 14.99, discount = 10, vat = 3;
Place this line near the top inside your function and object definitions.


Clean your memory

var price = 14.99, discount = 10, vat = 3;
//do something
//now clean up
price = discount = vat = null;

For simple data types, this seems silly. But for object and class variables, cleaning up is a must.


Use a Config section

Like so:
var my = ({});

my.Config = ({
title: "javascript coding guidelines",
showAlerts: true
});

my.showTitle = function () {
var C = my.Config;
if (C.showAlerts) {
window.alert(C.title)
}
C = null;
}



End statements with a semicolon

Avoid omitting semicolons where doing so may hinder legibility.


Avoid incremental operators

Don’t use i++, ++i, etc. Use i += 1 instead.


Use explicit type checks

Replace your == and != with type-safe === and !==.


Name your variables after what they are used for

x is less informative than intX, which is less informative than screenX, which, though more widespread and thus recognisable, is superseded by screen.coordinates.x.


Avoid premature name shortening

Bad:
var a, b, c, d, e, f, g;
a = "Message from me:\n\n";
b = window.alert;
c = function (msg) { b(a + msg) };
d = a.length;
c(d);


Better:
var my = ({});

my.Config = ({
alertPrefix: "Message from me:\n\n"
});

my.prefixedAlert = function (message) {
window.alert(my.Config.alertPrefix + message);
};

my.prefixedAlert("Hello, World!");


But, most of us are used to seeing constructs like these:
$("p").toggle();

for (var x in my.Config) alert(x);

for (i = 0; i < 16; i += 1) {
//do domething
}



Name your methods after why they are needed

Describe the reason for their existence. Try to capture that in as few words as possible. If you find yourself searching for words, or that your method names turn into sentences, try splitting the method up in a couple smaller ones.

For instance, this method is named after what it does:
function reduceAndReturnTotal(amounts) {
var total = 0;
if (Array.isArray(amounts)) {
total = amounts.reduce( function (last, current) {
return last + current;
});
}
return total;
}


And here is that same method, now named after why it exists:
function tallyOrder(prices) {
var tally = 0;
if (Array.isArray(prices)) {
tally = amounts.reduce( function (last, current) {
return last + current;
});
}
return tally;
}



When to create abstractions
“Code once, use often”, and “Once and only once”, are mantras brought to you by those who know that code re-use leads to less errors and easier maintenance. Unfortunately, that only holds true when you can actually reuse that code. And if you can, that’s good, go ahead and create a library. Otherwise, name you methods after their purpose.


Combine methods that belong together into their own object or class

Yes, we are telling you to orient your programming on objects.

Like so:
var my = ({});

my.Findlist = ({});

my.Findlist.add = function (value, label) {
//do something
}

my.Findlist.remove = function (value, label) {
//do something
}


Or in JSON:
var my = ({

Findlist: ({

add: function (value, label) {
//do something
}
,
remove: function (value, label) {
//do something
}

)}//end Findlist

)}//end my



Apply camel casing to method and variable names

These names are camel-cased:
cloneNode
getElementById
createElement

If you hadn’t recognised these names: they stem from the DOM javascript implementation as documented by W3C. Most web browsers comply to it.

Exception: use an Upper Case Initial for Classes and Constructors
Every time you define a Constructor (which results in an object that can be instantiated using the “new” keyword) or a singleton, start its name with a capitalized letter. Avoid upper case initials for any other variables, methods, objects, etc.


Use in-line instructions sparingly

Use an in-line instruction in the following cases:

In all other cases, write the instruction over several lines, or write a separate function to hold the instruction.

Bad:
//immediate execution of an anonymous function
window.alert( ( function (title, msg) { return title + "\n\n" + msg; } ("Hello", "World") ) );

//Array.prototype.filter()
myATerms = myTermsCollection.filter( function( term, index, collection) { return (term[0].toLowerCase() === 'a'); } );


More debuggable:
myACollection = myTermsCollection.filter (
function (term, index, collection) {
return (term[0].toLowerCase() === 'a');
}
);


More reusable:
function termStartsWith(term, index, collection) {
return (term[0].toLowerCase() === this.initial);
}
myACollection = myTermsCollection.filter(
termStartsWith, ({initial: 'a'})
);



Avoid reusing variables for different jobs

For instance: once you have defined a variable x as a string iterator, avoid reusing that same x as a number later on within the same scope.

Also, if you’ve chosen a specific name for a variable, make sure that you use it for the same purpose across scopes and methods.


Point once, refer often

This writes faster but runs slower:
if ($("#pushButton").css("display") === "block") {
$("#pushButton").css("text-decoration", "none");
$("#pushButton").html(my.Config.buttonPushLabel);
}


and this writes slower but runs faster:
var button = $("#pushButton").get(), style = button.style;
if (style.display === "block") {
style.textDecoration = "none";
button.innerHTML = my.Config.buttonPushLabel;
}
button = style = null;

Mind you that it isn’t the reduction of jQuery that leads to the speed increase; instead, it’s avoiding having to traverse the DOM with every instruction.


Double-quote strings, single-quote chars

Here’s an example:
var my = ({
person: ({
name : "Veltstra"
,
initial: 'A'
})
});



Make abstract array loops informative

Use these Ecmascript-262 Array functions: every, filter, forEach, map, reduce, and some.

Filtering example:
function termStartsWith(term, index, collection) {
return (term[0].toLowerCase() === this.initial);
}
myACollection = myTermsCollection.filter(
termStartsWith, ({initial: 'a'})
);



Prepend your Javascript files with a JavaDoc-like comment block

Preferably one that holds useful information, like so:
/**
* myJavascriptFile.js
* Description of why it is used...
*
* @use For template: thisPageType
* @author Our Company <us@here.now>
*/

The information you include should be relevant and helpful for your coworkers.


Automated checking of your code

Some of the above guidelines can be checked automatically. One of the free tools that can do this is JSLint.

JSLint itself complies to different guidelines, so do study its options. These options seem to work well for our own scripts:
/*jslint browser: true, sloppy: false, eqeq: false, vars: false, white: false, plusplus: false, maxerr: 50, indent: 2 */

Grammar checkers cannot check most semantic guidelines. So do us a favour and check the semantics yourself.

Need problem solving?

Talk to me. Let's meet for coffee or over lunch. Mail me at “code at omegajunior dot net”.

Clicky Analytics