This is my guide for writing consistent JavaScript code.
- JSCS
- JS Beautifier
- Indention
- Newline
- Trailing whitespace
- Semicolon
- Line break
- Line number
- Quotation mark
- Curly brace in decision block
- Chaining
- Variable declaration
- Function declaration
- Naming
- Array
- Object
- Equality
- Built-in
- Comment
- Type Casting And Coercion
- Multiline string literal
- Module
- Prototype
- Hoisting
- Error handling
Always use JSCS.
why?
JSCS is a code style linter for programmatically enforcing your style guide.
Always use JS Beautifier.
why?
To beautify your code.
- Use 4 spaces.
- Use soft TAB.
why?
- 4 spaces are improve readability.
- Use of spaces can produce a smaller file size.
Use UNIX-style newlines (\n
), and a newline character as the last character of a file.
why?
Windows-style newlines (\r\n
) are forbidden inside any repository.
Clean up any trailing whitespace in javascript files.
why?
Trailing whitespaces are unnecessary and improve the file size.
Always use semicolons.
why?
Leave semicolons is dangerous because it can make mask errors.
- Limit your lines to 100 characters.
- Place the break after an operator, ideally after a comma. The next line should be indented more 4 spaces.
why?
- Screens have gotten much bigger, but your brain has not.
- A break after an operator decreases the likelihood that a copy-paste error will be masked by semicolon insertion.
Keep max 40 lines per file.
why?
Easier to understand if you see everything without scrolling.
Use single quotes.
why?
This is helpful when creating strings that include HTML.
// BAD
var bad = "BAD";
var elem = "<input type=\"text\" />";
// GOOD
var good = 'GOOD';
var elem = '<input type="text" />';
Always use curly braces with multiline blocks (opening braces go on the same line as the statement).
why?
To omit braces is decrease readability.
// BAD
if (true) console.log('BAD');
// BAD
if (true)
{
console.log('BAD');
}
// GOOD
if (true) {
console.log('GOOD');
}
Use one method per line if you want to chain methods, and also indent these.
why?
Because it's easier to tell they are part of the same chain.
// BAD
var bad = new Bad();
bad
.methodOne()
.methodTwo()
.methodThree();
// BAD
var bad = new Bad();
bad.methodOne()
.methodTwo()
.methodThree();
// GOOD
var good = new Good();
good
.methodOne()
.methodTwo()
.methodThree();
- All variables should be declared before used.
- Avoid single var pattern and the var statements should be the first statement in the function body.
why?
- Use of global variables should be minimized.
- These are makes the program easier to read.
// BAD
var badString = 'I am BAD',
badElem = document.getElementById('bad-elem'),
badArr = ['one', 'two', 'three'],
badObj = {
'one': 1,
'two': 2,
'three': 3
};
// GOOD
var goodString = 'I am GOOD';
var goodElem = document.getElementById('good-elem');
var goodArr = ['one', 'two', 'three'];
var goodObj = {
'one': 1,
'two': 2,
'three': 3
};
- All functions should be declared before they are used.
- Inner functions should follow the var statement.
why?
- Use of global functions should be minimized.
- This helps make it clear what variables are included in its scope.
- Do not use reserved words.
- Use descriptive lowerCamelCase naming for variables, properties and functions except constructor functions.
- Constructor functions that must be used with the new prefix and UpperCamelCase naming.
why?
- Some identifiers are reserved words and cannot be used as variables or function names.
- For easier understanding.
- Bad things can happen if new is not used, so the capitalization convention is the only defense we have.
// BAD
var badname = 'I am BAD';
// BAD
var bad_name = 'underbar is BAD';
// BAD
var BADNAME = 'There is no constants in ECMAScript 5';
// BAD
var a = 'avoid single character names';
// GOOD
var goodName = 'I am GOOD';
Use Array literals instead of constructors.
why?
Array constructors are error-prone due to their arguments.
// BAD
var badArr = new Array();
// GOOD
var goodArr = [];
Single line Array initializer – no space after [ and before ].
// BAD
var badArr = [ 'one', 'two', 'three' ];
// GOOD
var goodArr = ['one', 'two', 'three'];
// multiline array initializer is BETTER
var goodArr = [
'one',
'two',
'three'
];
Never use Array as a map/hash/associative array.
why?
There is no associative arrays in javascript.
// BAD
var skills = [];
skills['Document language'] = 'HTML5';
var skills = {
'Document language': 'HTML5'
};
Use literal syntax for object creation.
why?
They don't have the constructor problem like Arrays, but be consistent.
// BAD
var badObj = new Object();
// GOOD
var goodObj = {};
Single line Object initializer – no space after { and before }.
// BAD
var badObj = { a: 0, b: 1, c: 2 };
// GOOD
var goodObj = {a: 0, b: 1, c: 2};
// multiline object initializer is BETTER
var goodObj = {
a: 0,
b: 1,
c: 2
};
Do not align to the colon.
// BAD
var badObj = {
bottom : 15,
left : 15,
right : 20,
top : 110
};
// GOOD
var goodObj = {
bottom: 15,
left: 15,
right: 20,
top: 110
};
Use === and !== operators.
why?
The == and != operators do type coercion before comparing.
Never extend the prototype of native JavaScript objects unless polyfilling.
why?
Hard to debug, and your future self will be forever grateful.
// BAD
Array.prototype.empty = function () {
return !this.length;
};
var badArr = [];
if (badArr.empty()) {
console.log('I am BAD');
}
// GOOD
var goodArr = [];
if (!goodArr.length) {
console.log('I am GOOD');
}
- Generally use single line comments.
- Place single line comments on a newline of subject and put an empty line before.
why?
- Save block comments for formal documentation.
- Empty lines above comments are improve readability.
// BAD
var bad = true; // comment in wrong place
// BAD
var bad;
// missing empty newline
bad = true;
// BAD
/*
block comments
for documentation
*/
var bad = true;
// GOOD
var good;
// set to true
good = true;
Use parseInt() for Numbers and always with the radix parameter.
why?
ECMAScript 5 specifies that 10 (decimal) is used, but not all browsers support this yet.
// BAD
var badSize = parseInt('16px');
// GOOD
var goodSize = parseInt('16px', 10);
Use Boolean() for Booleans without the new operator.
why?
The result with the new operator will be an Object (complex type), but without it will be a primitive type.
// BAD
var badBool = new Boolean(something);
// GOOD
var goodBool = Boolean(something);
Not use multiline string literals. Use string concatenation instead.
why?
The whitespace at the beginning of each line can't be safely stripped at compile time; whitespace after the slash will result in tricky errors; and while most script engines support this, it is not part of ECMAScript.
// BAD
var badStr = 'Veggies es bonus vobis, proinde vos postulo essum magis \
kohlrabi welsh onion daikon amaranth tatsoi tomatillo melon \
azuki bean garlic';
// GOOD
var goodStr = 'Veggies es bonus vobis, proinde vos postulo essum magis' +
'kohlrabi welsh onion daikon amaranth tatsoi tomatillo melon' +
'azuki bean garlic';
- Start modules with an Immediately Invoked Function Expression.
- Use strict mode.
why?
- In order to avoid global namespace pollution.
- Strict mode enables more warnings and makes JavaScript a cleaner language.
// BAD
var badModule = 'I want to be part of a module';
// GOOD
(function () {
'use strict';
var goodModule = 'IIFE is cool';
}());
Assign methods to the prototype object, instead of overwriting the prototype with a new object.
why?
Overwriting the prototype makes inheritance impossible: by resetting the prototype you'll overwrite the base.
// BAD
BadObj.prototype = {
badProp: 'I am bad',
badMethod: function () {
return 'bad';
}
};
// GOOD
GoodObj.prototype.goodProp = 'I am good';
GoodObj.prototype.goodMethod = function () {
return 'good';
};
Moving declarations to the top.
why?
Otherwise it cause an error, improve readability and easier to understand the code.
// BAD
function badWrapper () {
console.log(msg);
var msg = 'I am bad';
}
// GOOD
function goodWrapper () {
var msg = 'I am happy';
console.log(msg);
}
Try to use Exceptions
// GOOD
try {
throw new Error('Whoops!');
} catch (e) {
console.log(e.name + ': ' + e.message);
}