This is a guide for writing consistent and aesthetically pleasing JavaScript code in Green Global Co.,Ltd.
- 2 Spaces for indentation
- Newlines
- No trailing whitespace
- Use Semicolons
- 120 characters per line
- Use single quotes
- Use === and !== Operators
- Use {} and []
- Require padding inside curly braces
- Write small functions
- Return early from functions
- Name your closures
- No nested closures
- Method chaining
- Use 2 spaces for indenting your code
- Never mix tabs and spaces
If the editor supports, you should configure to show invisible characters.
- Use UNIX-style newlines (
\n
) - Always add a newline character as the last character of a file.
Must clean up any trailing whitespace before committing.
Always use semicolons.
Note that, semicolons should be included at the end of function expressions, but not at the end of function declarations. The distinction is best illustrated with an example:
var foo = app.user; // semicolon here.
var foo = {
key: 'abc',
value: 1234
}; // semicolon here.
var foo = function() {
return true;
}; // semicolon here.
function foo() {
return true;
} // NO semicolon here.
Keep lines shorter than 120 characters. It's better for lines to be too short than to be too long. Break up long lists, objects, and other statements onto multiple lines.
Use single quotes, unless you are writing JSON.
Good:
var foo = 'bar';
Bad:
var foo = "bar";
Use the === and !== operators. The == and != operators do type coercion and should not be used.
Good:
var a = 0;
if (a !== '') {
console.log('winning');
}
Bad:
var a = 0;
if (a == '') {
console.log('losing');
}
- Use {} instead of new Object()
- Use [] instead of new Array()
Use arrays when the member names would be sequential integers. Use objects when the member names are arbitrary strings or names.
Good:
var a = [1, 2, 3];
var b = { name: 'Albert' };
Bad:
var a = new Array(1, 2, 3);
var b = new Object();
b.name = 'Albert';
Good:
var user = { name: 'Alice', age: 15 };
var customer = {
name: 'Bob',
age: 16
};
Bad:
var user = {name: 'Alice', age: 15};
Very bad:
var user = {name:'Alice',age: 15};
In general, use functionNamesLikeThis, variableNamesLikeThis, ClassNamesLikeThis, EnumNamesLikeThis, methodNamesLikeThis, CONSTANT_VALUES_LIKE_THIS, foo.namespaceNamesLikeThis.bar, and filenameslikethis.js.
- Private properties and methods should be named with a trailing underscore.
- Protected properties and methods should be named without a trailing underscore (like public ones).
Declare one variable per var statement, it makes it easier to re-order the lines.
Good:
var keys = ['foo', 'bar'];
var values = [23, 42];
var object = {};
while (keys.length) {
var key = keys.pop();
object[key] = values.pop();
}
Bad:
var keys = ['foo', 'bar'],
values = [23, 42],
object = {},
key;
while (keys.length) {
key = keys.pop();
object[key] = values.pop();
}
Your opening braces go on the same line as the statement.
Good:
if (isAudio(source)) {
return estimateAudio(source);
} else if (isMovie(source)) {
return estimateMovie(source);
}
Bad:
// Stroustrup style: https://en.wikipedia.org/wiki/Indent_style#Variant:_Stroustrup
if (isAudio(source)) {
return estimateAudio(source);
}
else if (isMovie(source)) {
return estimateMovie(source);
}
// Allman style: https://en.wikipedia.org/wiki/Indent_style#Allman_style
if (isAudio(source))
{
return estimateAudio(source);
}
else if (isMovie(source))
{
return estimateMovie(source);
}
Also, notice the use of whitespace before and after the condition statement.
A for class of statements should have the following form:
for (initialization; condition; update) {
statements
}
for (variable in object) {
if (filter) {
statements
}
}
The first form should be used with arrays and with loops of a predeterminable number of iterations.
The second form should be used with objects. Be aware that members that are added to the prototype of the object will be included in the enumeration. It is wise to program defensively by using the hasOwnProperty method to distinguish the true members of the object:
for (variable in object) {
if (object.hasOwnProperty(variable)) {
statements
}
}
A while statement should have the following form:
while (condition) {
statements
}
A do statement should have the following form:
do {
statements
} while (condition);
The if class of statements should have the following form:
if (condition) {
statements
}
if (condition) {
statements
} else {
statements
}
if (condition) {
statements
} else if (condition) {
statements
} else {
statements
}
A switch statement should have the following form:
switch (expression) {
case expression:
statements
case expression:
statements
default:
statements
}
Each group of statements (except the default) should end with break, return, or throw, or a comment indicating a fall-through.
The try class of statements should have the following form:
try {
statements
} catch (variable) {
statements
}
try {
statements
} catch (variable) {
statements
} finally {
statements
}
Use trailing commas and put short declarations on a single line. Only quote keys when your interpreter complains:
Good:
var fo = {
good: 'code',
'is generally': 'pretty',
};
Bad:
var a = [
'hello', 'world'
];
var b = {"good": 'code'
, is generally: 'pretty'
};
Keep your functions short. A good function fits on a slide that the people in the last row of a big room can comfortably read. So don't count on them having perfect vision and limit yourself to ~15 lines of code per function.
To avoid deep nesting of if-statements, always return a function's value as early as possible.
Good:
function isPercentage(val) {
if (val < 0) {
return false;
}
if (val > 100) {
return false;
}
return true;
}
Bad:
function isPercentage(val) {
if (val >= 0) {
if (val < 100) {
return true;
} else {
return false;
}
} else {
return false;
}
}
Or for this particular example it may also be fine to shorten things even further:
function isPercentage(val) {
var isInRange = (val >= 0 && val <= 100);
return isInRange;
}
Feel free to give your closures a name. It shows that you care about them, and will produce better stack traces, heap and cpu profiles.
Good:
req.on('end', function onEnd() {
console.log('winning');
});
Bad:
req.on('end', function() {
console.log('losing');
});
One method per line should be used if you want to chain methods.
You should also indent these methods so it's easier to tell they are part of the same chain.
Good:
User
.findOne({ name: 'foo' })
.populate('bar')
.exec(function(err, user) {
return true;
});
Bad:
User
.findOne({ name: 'foo' })
.populate('bar')
.exec(function(err, user) {
return true;
});
User.findOne({ name: 'foo' })
.populate('bar')
.exec(function(err, user) {
return true;
});
User.findOne({ name: 'foo' }).populate('bar')
.exec(function(err, user) {
return true;
});
User.findOne({ name: 'foo' }).populate('bar')
.exec(function(err, user) {
return true;
});
Use slashes for both single line and multi line comments. Try to write comments that explain higher level mechanisms or clarify difficult segments of your code. Don't use comments to restate trivial things.
Add empty lines before or after comments to make the it easier to read.
A copyright notice and author information are optional. File overviews are generally recommended whenever a file consists of more than a single class definition. The top level comment is designed to orient readers unfamiliar with the code to what is in this file. If present, it should provide a description of the file's contents and any dependencies or compatibility information. As an example:
/**
* Description of file, its uses and information
* about its dependencies.
* @creator: toanpc
* @contributors: binhqd, ducl, thanhnt
* Copyright 2015, Green Global Co.,Ltd.
*/
If the project requires auto-generating documentation, all files, classes, methods and properties should be documented with ESDoc. Textual descriptions for properties, methods, method parameters and method return values should be included unless obvious from the property, method, or parameter name.
Complete sentences are recommended but not required. Complete sentences should use appropriate capitalization and punctuation.
Example:
/**
* What a great class this is!
* @example
* let myClass = new MyAwesomeClass(foo, bar);
*/
class MyAwesomeClass {
/**
* Constructor for my awesome class
* @param {number} foo The foo for my awesome class
* @param {string} bar The bar for my awesome class
*/
constructor(foo, bar) {...}
/**
* @emits {my.event} Emit an event
*/
myEvent() {...}
}
If you have to line break a block tag, you should treat this as breaking a code statement and indent it four spaces.
/**
* Illustrates line wrapping for long param/return descriptions.
* @param {string} foo This is a param with a description too long to fit in
* one line.
* @return {number} This returns something that has a description too long to
* fit in one line.
*/
project.MyClass.prototype.method = function(foo) {
return 5;
};
Do not do this:
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.';
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.
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.';
This is the best way before ES6:
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.'
].join(' ');
With ECMAScript 2015, you should do this:
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.`
Do not extend the prototype of native JavaScript objects. Your future self will be forever grateful.
Good:
var a = [];
if (!a.length) {
console.log('winning');
}
Bad:
String.prototype.trim = function(s) {
return s.replace(/^[\s\xa0]+|[\s\xa0]+$/g, '');
}
Array.prototype.empty = function() {
return !this.length;
}
var a = [];
if (a.empty()) {
console.log('losing');
}
These statements should not be used.
This style guide is inspired by what is popular within the community, and the best practices from:
- Google JavaScript style guide
- Node.js Style Guide
- npm's "funny" coding style
- Douglas Crockford: Code Conventions for the JavaScript Programming Language
- Addy Osmani: JavaScript Style Guides And Beautifiers
- ESLint recommended rules
BE CONSISTENT.
If you're editing code, take a few minutes to look at the code around you and determine its style. If they use spaces around all their arithmetic operators, you should too. If their comments have little boxes of hash marks around them, make your comments have little boxes of hash marks around them too.
The point of having style guidelines is to have a common vocabulary of coding so people can concentrate on what you're saying rather than on how you're saying it. We present global style rules here so people know the vocabulary, but local style is also important. If code you add to a file looks drastically different from the existing code around it, it throws readers out of their rhythm when they go to read it. Avoid this.