Home

Awesome

JavaScript Style Guide - Abstract

I see a lot of new or existing JavaScript developers are not coding in the proper way in my office. I always see things which can be improved on their codebase, but I can't help them much because I moved to the most busiest Ruby team. I understand that JavaScript is the most misunderstood language, but many people is able to catch it up fairly well.

Two years before I left JavaScript, I was intended to do presentation about what are the most common mistakes in the my office. However, I failed to do it because of some reasons. A few months ago I see there are a Ruby and Rails Style Guide. I think I should do one on JavaScript Style Guide.

There are many sources I've combined into the below documents. You could see the link for more details in each topic and in the References section. The main ones are from Google Javascript Style Guide, JavaScript Patterns from Addy Osmani, JavaScript Object-Oriented Programming from Mozilla. Here, I took most of the good parts and write up in a bit more details to clarify.

Anyway, welcome your feedbacks. (The work is in progress.)

Table of Contents

<a name="language"/> # JavaScript Language Rules <a name="var"/> ## var * Always declare variables with var. * If you forget to declare with var keyword, that variable will be placed in the global context. Sometimes, it's hard to debug the problems.
```JavaScript
function test() {
  a = "hello";
}
alert(a);
```
<a name="constants"/> ## Constants * Use NAMES_LIKE_THIS for constants. * As for the const keyword, Internet Explorer doesn't parse it, so don't use it.
```JavaScript
goog.example.SECONDS_IN_A_MINUTE = 60;
```
<a name="semicolons"/> ## Semicolons * Always use semicolons. Always end your assignment statements with semicolons.
```JavaScript
MyClass.prototype.myMethod = function () {
  return 42;
};

var x = {
  'i': 1,
  'j': 2
};

var THINGS_TO_EAT = [apples, oysters, sprayOnCheese];
```
<a name="nested"> ## Nested functions * Nested functions can be very useful for the task of hiding helper functions.
```JavaScript
function hypotenuse(a, b) {
  function square(x) { return x*x; }
  
  return Math.sqrt(square(a) + square(b));
}
```
<a name="function"> ## Function declarations within blocks * Never declare function within blocks. Do not do this:
```JavaScript
if (x) {
  function foo() {}
}
```
<a name="wrapper"> ## Wrapper objects for primitive types * Don't use wrapper objects for primitive types.
```JavaScript
var x = new Boolean(false);
if (x) {
  alert('hi');  // Shows 'hi'.
}
```
<a name="method"> ## Method definitions * The preferred style of declaring method definition is:
```JavaScript
Foo.prototype.bar = function () {
  /* ... */
};
```
<a name="eval"> ## eval() * Use eval only for parsing ajax response.
```JavaScript
var userOnline = false;
var user = 'nusrat';
var xmlhttp = new XMLHttpRequest();
xmlhttp.open('GET', 'http://chat.google.com/isUserOnline?user=' + user, false);
xmlhttp.send('');
// Server returns:
// userOnline = true;
if (xmlhttp.status == 200) {
  eval(xmlhttp.responseText);
}
```
<a name="with"> ## with() {} * Local variables may collide with the property's object of the with statement. It would be a good idea not to use the with statement because it may change the meaning of your program.
```JavaScript
with (foo) {
  var x = 3;
  return x;
}
```

Instead of this:

```JavaScript
with (ooo.eee.oo.ah_ah.ting.tang.walla.walla) {
  bing = true;
  bang = true;
}
```

you could do this:

```JavaScript
var o = ooo.eee.oo.ah_ah.ting.tang.walla.walla;
o.bing = true;
o.bang = true;
```
<a name="this"> ## this * The semantics of this can be tricky. At times, it refers to: * the global object (in most places)
```JavaScript
function foo() {
  this.bar = "hello"
};

foo();
alert(bar);  // Shows 'hello'.
```
<a name="for"> ## for-in loop * Only for iterating over keys in an object/map/hash, NOT in an Array. * for-in does not loop from 0 to length - 1 but over all the present keys in the object and its prototype chain.
```JavaScript
function printArray(arr) {
  for (var key in arr) {
    print(arr[key]);
  }
}

printArray([0,1,2,3]);  // This works.

var a = new Array(10);
printArray(a);  // This is wrong.

a = document.getElementsByTagName('*');
printArray(a);  // This is wrong.

a = [0,1,2,3];
a.buhu = 'wine';
printArray(a);  // This is wrong again.

a = new Array;
a[3] = 3;
printArray(a);  // This is wrong again.
```
<a name="associative"> ## Associative Arrays * Never use Array as a map/hash/associative array (more precisely you are not allowed to use non number indexes for arrays). * If you need a map/hash use Object instead of Array in these cases because the features that you want are actually features of Object and not of Array. <a name="multiline"> ## Multiline string literals * Do not do this:
```JavaScript
var myString = 'A rather long string of English text, an error message \
                actually that just keeps going and going -- an error \
                message to make the Energizer bunny blush (right through \
                those Schwarzenegger shades)! Where was I? Oh yes, \
                you\'ve got an error and all the extraneous whitespace is \
                just gravy.  Have a nice day.';
```
<a name="array"> ## Array and Object literals * Use Array and Object literals instead. * Array constructors are error-prone due to their arguments.
```JavaScript
// Length is 3.
var a1 = new Array(x1, x2, x3);

// Length is 2.
var a2 = new Array(x1, x2);

// If x1 is a number and it is a natural number the length will be x1.
// If x1 is a number but not a natural number this will throw an exception.
// Otherwise the array will have one element with x1 as its value.
var a3 = new Array(x1);

// Length is 0.
var a4 = new Array();
```
<a name="modifying"> ## Modifying prototypes of builtin objects * Modifying builtins like Object.prototype and Array.prototype are strictly forbidden. * Modifying other builtins like Function.prototype is less dangerous but still leads to hard to debug issues in production and should be avoided. <a name="data"> ## Data Access * Based on the book "High Performance JavaScript": * Literal value and local variable access tend to be faster than array item and object member access. * Always store out-of-scope values in local variables if used more than once because older browsers take much larger amount of time taken to access values.
```JavaScript
function initUI() {
  var bd = document.body,
      links = document.getElementsByTagName("a"),
      i= 0,
      len = links.length;

  while (i < len) {
    update(links[i++]);
  }

  document.getElementById("go-btn").onclick = function () {
    start();
  };

  bd.className = "active";
}
```

It could be written in this way by declaring local variables:

```JavaScript
function initUI() {
  var doc = document,
      bd = doc.body,
      links = doc.getElementsByTagName("a"),
      i = 0,
      len = links.length;

  while(i < len) {
    update(links[i++]);
  }

  doc.getElementById("go-btn").onclick = function () {
    start();
  };

  bd.className = "active";
}
```

* Older browsers, IE and FF 3.5, incur a performance penalty with each additional step into the prototype chain. 
* The nested members such as "window.location.href" causes the javascript engine to go through the object member resolution process two times (the number of dots).

```JavaScript
function toggle(element) {
  if (YAHOO.util.Dom.hasClass(element, "selected")) {
    YAHOO.util.Dom.removeClass(element, "selected");
    return false;
  } else {
    YAHOO.util.Dom.addClass(element, "selected");
    return true;
  }
}
```

It would be written in this way:

```JavaScript
function toggle(element) {
  var Dom = YAHOO.util.Dom;
  if (Dom.hasClass(element, "selected")) {
    Dom.removeClass(element, "selected");
    return false;
  } else {
    Dom.addClass(element, "selected");
    return true;
  }
}
```
<a name="closure"> ## Closure <a name="style"> # JavaScript Style Rules <a name="naming"> ## Naming * In general, use: * functionNamesLikeThis, * variableNamesLikeThis, * ClassNamesLikeThis, * EnumNamesLikeThis, * methodNamesLikeThis, * SYMBOLIC_CONSTANTS_LIKE_THIS, * onEventHandlerFunction <a name="formatting"> ## Code formatting * Always use braces on if/else even though it has only statement. * Always start your curly braces on the same line.
```JavaScript
if (something) {
  // ...
} else {
  // ...
}
```
<a name="string"> ## String * Prefer ' over " For consistency single-quotes (') are preferred to double-quotes ("). This is helpful when creating strings that include HTML:
```JavaScript
var msg = 'This is some HTML';
```
<a name="tidbits"> ## JavaScript tidbits * True and False Boolean Expressions The following are all false in boolean expressions:
  * null
  * undefined
  * '' the empty string
  * 0 the number

  But be careful, because these are all true:

  * '0' the string
  * [] the empty array
  * {} the empty object

Instead of this:

```JavaScript
while (x != null) {
```

you can write this:

```JavaScript
while (x) {
```

Instead of this:

```JavaScript
if (y != null && y != '') {
```

you can write this:

```JavaScript
if (y) {
```
<a name="object"> # JavaScript Object Oriented Programming JavaScript doesn't support the concept of classes in nature. We need some javascript patterns to emulate this behaviour. Thanks to [Douglas Crockford](http://javascript.crockford.com/private.html). <a name="constructor"> ## Constructor and Public Members * In JavaScript, constructors are just function, constructor function. We use this to create objects from this function. Usually, we capitalize the name of constructor function and use the 'new' operator to instantiate a new object. * Inside a constructor, the keyword 'this' references the new object that's being created. We define properties inside constructor and define methods inside the constructor's prototype. * With this pattern, all methods are created off of the prototype, which means there is only one copy of each in memory, no matter how many instances you create.
```JavaScript
function Car(model, year, miles) {

  // public attributes
  this.model = model;
  this.year = year;
  this.miles = miles;
}

/*
 Note here that we are using Object.prototype.newMethod rather than 
 Object.prototype so as to avoid redefining the prototype object.
 Public methods
*/
Car.prototype.toString = function () {
  return this.model + " has done " + this.miles + " miles";
};

var civic = new Car("Honda Civic", 2009, 20000);
var mondeo = new Car("Ford Mondeo", 2010, 5000);

console.log(civic.toString());
```
<a name="private"> ## Private Members * There are two usual ways to implement private members: * through naming convention: an underscore is added to name of members. This signifies they are for internal use only.
```JavaScript
function Car(model, year, miles) {

  // private members through convention
  this._model = model;
  this._year = year;
  this._miles = miles;
}

Car.prototype._setAttribute(name, value) {
    this["_" + name] = value;
};

Car.prototype.setModel = function(model) {
    this._setAttribute('model', model);
};

Car.prototype.getModel = function () {
  return this._model;
};
```
<a name="static"> ## Static Members
```JavaScript
var Book = (function () {
  var numOfBooks = 0; // Private static attributes. 
  function checkIsbn(isbn) { // Private static method. ... } 

  // Return the constructor. 
  return function(newIsbn, newTitle, newAuthor) { 
    var isbn; // Private attributes.
    this.getIsbn = function () { // Privileged methods. 
      return isbn;
    };

    this.setIsbn = function(newIsbn) {
      if(!checkIsbn(newIsbn)) throw new Error('Book: Invalid ISBN.');
      isbn = newIsbn;
    }; 
    numOfBooks++; // Keep track of how many Books have been created 
    this.setIsbn(newIsbn);
  }
})();

Book.convertToTitleCase = function(inputString) { // Public static method.
  ...
};
Book.prototype = { // Public, non-privileged methods.
  display: function () {
    ...
  } 
}; 
```
<a name="inheritance"> ## Inheritance
```JavaScript
function Employee(name, dept) {
  this.name = name || "";
  this.dept = dept || "";
}

function Engineer(name, machine) {

  // 1. calling the superclass's constructor
  Employee.call(this, name, "engineering");
  this.machine = machine;
}

// 2. setup the prototype chain
Engineer.prototype = new Employee();
```
<a name="mixin"> ## Mixin * This is another way to make our code reuse without inheritance. In practice, you create an object that contains your general-purpose methods, and then use it to augment/extend other classes. It is generally not instantiated or called directly, instead it exists to provide methods to other classes. * For more detail, check this [blog post](http://javascriptweblog.wordpress.com/2011/05/31/a-fresh-look-at-javascript-mixins/).
```JavaScript
var circleFns = {
  area: function () {
    return Math.PI * this.radius * this.radius;
  },
  grow: function () {
    this.radius++;
  },
  shrink: function () {
    this.radius--;
  }
};

/*
  The extend method will simply copy all methods from destination to source.
  Here, make sure that method belongs to, not inherited methods, the destination object.
*/
function extend(destination, source) {
  for (var k in source) {
    if (source.hasOwnProperty(k)) {
      destination[k] = source[k];
    }
  }
  return destination;
}

var RoundButton = function(radius, label) {
  this.radius = radius;
  this.label = label;
};

extend(RoundButton.prototype, circleFns);
extend(RoundButton.prototype, buttonFns);
```
<a name="patterns"> # JavaScript Common Patterns * Thanks to Addy Osmani, the author of this [online book](#http://addyosmani.com/resources/essentialjsdesignpatterns/book/) for his excellent write-up. I've learnt quite a lot from this. <a name="module"> ## The Module Pattern * This is the most common pattern in JavaScript. It was originally formally defined by Douglas Crockford (JavaScript: The Good Parts). * You probably have heard about "Global variables are evil", and this pattern allows us to define public/private members which means that you avoid polluting or clobbering the global namespaces. You will have a level of shielding from external entities accessing your 'hidden' information.
```JavaScript
var someModule = (function () {

  //private attributes
  var privateVar = 5;

  //private methods
  var privateMethod = function () {
    return 'Private Test';
  };

  return {

    //public attributes
    publicVar: 10,

    //public methods
    publicMethod: function () {
      return ' Followed By Public Test ';
    },

    //let's access the private members
    getData: function () {
      return privateMethod() + this.publicMethod() + privateVar;
    }
  }
})(); //the parent here cause the anonymous function to execute and return

someModule.getData();
```
<a name="revealing"> ## The Revealing Module Pattern * Here is a slightly improved version - [Christian Heilmann’s Revealing Module pattern](http://christianheilmann.com/2007/08/22/again-with-the-module-pattern-reveal-something-to-the-world/) * The benefits of this pattern is that it makes very clear at the end which of your functions and variables may be accessed publicly. Moreover, you are able to reveal private functions with different name.
```JavaScript
var myRevealingModule = (function () {
  var name = 'John Smith';
  var age = 40;

  function updatePerson() {
    name = 'John Smith Updated';
  }
  function setPerson() {
     name = 'John Smith Set';
  }
  function getPerson() {
     return name;
  }

  return {
      set: setPerson,
      get: getPerson
  };
})();

// Sample usage:
myRevealingModule.get();
```
<a name="references"> # References * http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml * http://addyosmani.com/resources/essentialjsdesignpatterns/book * http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth * https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript * https://developer.mozilla.org/en/JavaScript/A_re-introduction_to_JavaScript * http://javascript.crockford.com/private.html * http://javascriptweblog.wordpress.com/2011/05/31/a-fresh-look-at-javascript-mixins/ * http://greasemonkey.github.com/style.html