Skip to content

Latest commit

 

History

History
600 lines (480 loc) · 12.5 KB

File metadata and controls

600 lines (480 loc) · 12.5 KB

JavaScript CodeStyle

##General

  • Files should be encoded in UTF-8 without BOM.
  • The recommended line-break character is LF - \n.
  • Files should end with a LF character.
  • One level of indentation is achieved with 4 space characters.
  • Lines should be no longer than 120 characters.
  • Trailing whitespace at the end of lines should be removed.

##Naming

  • variableNamesLikeThis
  • functionNamesLikeThis
  • functionArgumentsLikeThis
  • ClassNamesLikeThis
  • methodNamesLikeThis
  • CONSTANTS_LIKE_THIS
  • namespacesLikeThis
  • events-like-this
  • private or protected properties and methods should be prefixed with a single _ character
  • Shortened and abbreviated names should be avoided.
  • Common abbreviations, such as JSON and XML are written in CamelCase. For example: Json, Xml.

##Variable declaration

  • Each variable should be declared:

    • using a var statement;
    • only once in the current scope;
    • on a new line;
    • as close as possible to the place where it's first used.
  • Each var statement should have only one variable declared in it.

Good:

var keys = ['foo', 'bar'];
var values = [23, 42];

var object = {};
while (items.length) {
    var key = keys.pop();
    object[key] = values.pop();
}

Bad:

var keys = ['foo', 'bar'],
    values = [23, 42],
    object = {},
    key;

while (items.length) {
    key = keys.pop();
    object[key] = values.pop();
}

##Literals

###Objects

  • There should be no whitespace after the opening and before the closing curly braces:
var obj = {a: 1, b: 2, c: 3};

this.method({a: 1, b: 2});
  • There should be no whitespace characters before the colon:
var obj = {
    prop: 0
};
  • Only property names should be aligned within object literals:

Good:

var obj = {
    a: 0,
    b: 1,
    lengthyName: 2
};

Bad:

var obj = {
    a          : 0,
    b          : 1,
    lengthyName: 2
};
  • Quotes around property names should be typed only if needed:

Good:

var obj = {
    key: 0,
    'key-key': 1
};

Bad:

var obj = {
    'key': 0,
    'key-key': 1
};

###Arrays

  • When enumerating elements in an array literal, spaces should be typed after the comma only:
var fellowship = ['foo', 'bar', 'baz'];

###Strings

  • String literals should use single quotes:
var lyrics = 'Never gonna give you up. Never gonna let you down. Never gonna turn around and desert you.';
  • If a string contains a single quote character, it should be escaped:
var test = 'It shouldn\'t fail';

##Semicolons Statements should always end with a semicolon.

##Keywords

  • Keywords are always followed by a single space character:
if (test) {
    // ...
}

function foo() {
    // ...
}

var bar = function () {
    // ...
};
  • If the keyword is followed by a semicolon, there should be no space between them:
return;

##Block Statements

  • The opening curly brace should be on the same line and separated with one space character:
if (test) {
    // ...
}

function foo() {
    // ...
}
  • Branching and looping statements should always be surrounded with curly braces:

Good:

if (test) {
    return;
}

Bad:

if (test)
    return;

if (test) return;

if (test) { return; }

##Conditional Statements ###if

  • The else keyword should be on the same line as the closing brace of the if-part of the statement:
if (test) {
    // ...
} else {
    // ...
}
  • Condition statements should not contain assignment operations:

Good:

var foo = bar();
if (foo > 0) {
    // ...
}

Bad:

var foo;
if ((foo = bar()) > 0) {
    // ...
}
  • Logical operators should not be used for conditional branching:

Good:

if (condition) {
    actionIfTrue();
} else {
    actionIfFalse();
}

Bad:

condition && actionIfTrue() || actionIfFalse();
if (longCondition ||
    anotherLongCondition &&
    yetAnotherLongCondition
) {
    // ...
}

Good:

if (getType() === 'driving') {

}

Bad:

if ('driving' === getType()) {

}

###switch The switch statement should be written as in the example:

switch (value) {
    case 1:
        // ...
        break;

    case 2:
        // ...
        break;

    default:
        // ...
        // no break keyword on the last case
}

##Loops ###for If possible, Array.prototype.forEach should be used instead of a for loop.

[1, 2, 3].forEach(function (value) {
    console.log(value);
});

Performance-critical parts of the code can use a for statement.

###for (var i in obj) If possible, Object.keys should be used instead of a for-in construction.

Object.keys(obj).forEach(function (key) {
    console.log(key);
});

##Operators ###'with' operator

The with operator should not be used.

###Comparison Operators If there is no need for type casting, the strict equality operator === (or strict inequality !==) should be used.

###Ternary Operator The ternary operator should be written as in the examples:

var x = a ? b : c;

var y = a ?
    longButSimpleOperandB : longButSimpleOperandC;

var z = a ?
    moreComplicatedB :
    moreComplicatedC;

###Unary Operators Unary operators should be typed without whitespace between them and their operands:

var foo = !bar;

Exceptions from this rule are the unary special JS operators).

##eval The eval function should be avoided. json serialized data should be parsed with JSON.parse.

##undefined Checking for undefined values should be done using the strict equality operator.

Good:

x === undefined;

Bad:

typeof x === 'undefined'

x === void 0

##Parentheses

  • Should be used only if it is required of the expression's syntax or semantics.
  • Should not be used with the unary operators delete, typeof and void, or with the keywords return, throw and new.

##Exceptions throw should be used with new Error or an object of a class derived from Error:

Good:

throw new Error('msg');

Bad:

throw 'msg';

##Type Casting Type casting should be done explicitly:

Good:

Boolean(foo)
Number(bar)
String(baz)
[].indexOf(qux) === -1 or [].indexOf(qux) < 0

Bad:

!!foo
+bar
baz + ''
~[].indexOf(qux)

##Multi-Line Statements

  • If a statement is longer than the maximum line length, it is split into several lines and properly indented.
  • Lines of the statement should be split after an operator:
var debt = this.calculateBaseDebt() + this.calculateSharedDebt() + this.calculateDebtPayments() +
    this.calculateDebtFine();
  • Closing parentheses should be on a new line with the indentation of the current block statement:

Good:

DoSomethingThatRequiresALongFunctionName(
    veryLongArgument1,
    argument2,
    argument3,
    argument4
);
anotherStatement;

Bad:

DoSomethingThatRequiresALongFunctionName(
    veryLongArgument1,
    argument2,
    argument3,
    argument4);
anotherStatement;

##Method Chaining When a method is called on a new line, it should:

  • Be one indentation level deeper than the target object.
  • Begin with the property access operator ..

Good:

someObject
    .operation()
    .operationWithCallback(function (obj) {
        obj.processed = true;
    })
   .end();

Bad:

someObject.
   start().
   end();

someObject
.start()
.end();

##String concatenation

  • Strings should be concatenated with the + operator.
  • The [].join('') should be avoided.
  • Escaping newline literals inside strings should be avoided.

Good:

var foo = '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.';

Bad:

var foo = '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.';

##Empty Lines A single empty line can be used as a separator for grouping the code into logical blocks:

doSomethingTo(x);
doSomethingElseTo(x);
andThen(x);

nowDoSomethingWith(y);

andNowWith(z);

##Function Context

doAsync(function () {
    this.fn();
}.bind(this));
  • Preferably, the context argument should be used (if available):

Good:

[1, 2, 3].forEach(function (n) {
    this.fn(n);
}, this);

Bad:

[1, 2, 3].forEach(function (n) {
    this.fn(n);
}.bind(this));
  • If assigning the current context to a variable, the variable should be named _this:
var _this = this;
doAsync(function () {
    _this.fn();
});

##Comments

  • In-line comments should start with //. Between the // and the text of the comment should be one space character.
  • Comments for functions, classes, etc. should be written according to the jsdoc documentation syntax.

##Classes

  • "Symmetrical" methods should be declared one after the other. For example:
var FooClass = inherit({
    __constructor: function () {},

    // destructors are placed right after the constructor
    destruct: function () {},

    someMethod: function () {}
});

##node.js

###Importing Modules

  • Modules should be imported in the beginning of the file, after the description of the module (if present):

Good:

var http = require('http');
var fs = require('fs');

// code here

Bad:

var http = require('http');

// code here

var fs = require('fs');

// code here

This rule does not apply to modules that are imported "on demand".

  • Module import calls should be grouped according to the following order:
  1. Standard node.js modules (i.e. fs, util, etc.).
  2. External lib modules.
  3. Modules of the current application.