There are some aspects of Catberry code style below:
- Formatting
- JavaScript
- Naming
- Variables
- Objects
- Arrays
- Types
- Functions
- Strings
- Blocks
- Comments
- Code Quality Tools
-
Always use tabs (hard tabs)
-
Never leave trailing whitespaces
-
Never use multiple line breaks
-
Maximum length of line — 80
-
Always use semicolons
-
Always use a space after keywords and before curly braces
// bad if(some){ }else{ } // good if (some) { } else { }
-
Set off operators with spaces.
// bad var x=y+5; // good var x = y + 5;
-
Use indentation when making long method chains.
// bad $('#items').find('.selected').highlight().end().find('.open').updateCount(); // good $('#items') .find('.selected') .highlight() .end() .find('.open') .updateCount();
-
Never use leading commas
// bad var once , upon , aTime; // good var once, upon, aTime;
-
Always use curly braces where it's possible, the first brace on same line and space before it
// bad if (condition) { } if(condition2){ } // good if (condition) { }
- Use ECMAScript 5.1 syntax (ECMA-262)
- Always use JavaScript Strict Mode at the beginning of each .js file.
- Never use with, let or void operator
- Maximum arguments in function — 5
- Maximum code block depth — 3
- Maximum statement count per function — 50
- Maximum cyclomatic complexity - 10
-
Always use
camelCase
for variables,PascalCase
for constructors andUPPER_CASE
with underscores for constantsvar SOME_CONSTANT = 42; function Constructor() { var someVariable = 'someValue'; }
-
Avoid single letter names. Be descriptive with your naming.
// bad function q() { // ...stuff... } // good function query() { // ..stuff.. }
-
Use a leading underscore
_
when naming private properties// bad this.__firstName__ = 'Panda'; this.firstName_ = 'Panda'; // good this._firstName = 'Panda';
-
When saving a reference to
this
use nameself
.// bad function() { var _this = this; return function() { console.log(_this); }; } // good function() { var self = this; return function() { console.log(self); }; }
-
If the variable is boolean type then start its name with
is
orhas
prefix// bad var success = true; // good var isSuccess = true;
-
If JavaScript file has definition of a constructor it should have a name of this constructor in PascalCase like
Constructor.js
-
Always use
var
to declare variables. Not doing so will result in global variables. We want to avoid polluting the global namespace.// bad superPower = new SuperPower(); // good var superPower = new SuperPower();
-
Use one
var
declaration for multiple variables and declare each variable on a newline.// bad var items = getItems(); var goSportsTeam = true; var dragonBall = 'z'; // good var items = getItems(), goSportsTeam = true, dragonBall = 'z';
-
Declare unassigned variables last. This is helpful when later on you might need to assign a variable depending on one of the previously assigned variables.
// bad var i, len, dragonBall, items = getItems(), goSportsTeam = true; // bad var i, items = getItems(), dragonBall, goSportsTeam = true, len; // good var items = getItems(), goSportsTeam = true, dragonBall, length, i;
-
Assign variables at the top of their scope. This helps avoid issues with variable declaration and assignment hoisting related issues.
// bad function () { test(); console.log('doing stuff..'); //..other stuff.. var name = getName(); if (name === 'test') { return false; } return name; } // good function () { var name = getName(); test(); console.log('doing stuff..'); //..other stuff.. if (name === 'test') { return false; } return name; } // bad function () { var name = getName(); if (!arguments.length) { return false; } return true; } // good function () { if (!arguments.length) { return false; } var name = getName(); return true; }
-
Always use the literal syntax for object creation.
// bad var item = new Object(); // good var item = {};
-
When possible do not use delete operator. In some, cases it can cause performance degradation.
-
Use dot notation when accessing properties.
var luke = { jedi: true, age: 28 }; // bad var isJedi = luke['jedi']; // good var isJedi = luke.jedi;
-
Use subscript notation
[]
when accessing properties with a variable.var luke = { jedi: true, age: 28 }; function getProp(prop) { return luke[prop]; } var isJedi = getProp('jedi');
-
Always use the literal syntax for array creation.
// bad var array = new Array(); // good var array = [];
-
Edit array items only using:
var array = [1, 2, 3];
// bad
array[array.length] = 'some';
// good
array.push('some');
- Use functional approach when working with arrays. Use methods like:
- every
- filter
- indexOf
- forEach
- map
- reduce
- reduceRight
- reverse
- some
- sort
var array = [1, 2, 3, 4, 5];
// bad
var hasGreaterThanThree = false;
for (var i = 0; i < array.length; i++) {
if (array[i] > 3) {
hasGreaterThanThree = true;
break;
}
}
// good
var hasGreaterThanThree = array.some(function (item) {
return item > 3;
});
-
To convert an array-like object to an array, use the slice like this
var args = Array.prototype.slice.call(arguments);
-
When you need to copy an array use slice like this
var items = [1, 2, 3, 4, 5], itemsCopy = items.slice();
-
Always use explicit type conversion with
Number
,Boolean
andString
(.toString()
) functions// bad var boolean = !!some, number = +some, string = '' + some, hasDot = ~string.indexOf('.'); // good var boolean = Boolean(some), number = Number(some), string = String(some), string = some.toString(), hasDot = string.indexOf('.') !== -1;
-
Function expressions:
// anonymous function expression var anonymous = function () { return true; }; // named function expression var named = function named() { return true; }; // immediately-invoked function expression (IIFE) (function () { console.log('Welcome to the Internet. Please follow me.'); })();
-
Never declare a function in a non-function block (if, while, etc). Assign the function to a variable instead. Browsers will allow you to do it, but they all interpret it differently.
Note: ECMA-262 defines a
block
as a list of statements. A function declaration is not a statement. Read ECMA-262's note on this issue.// bad if (currentUser) { function test() { console.log('Nope.'); } } // good var test; if (currentUser) { test = function test() { console.log('Yup.'); }; }
-
Never name a parameter
arguments
, this will take precedence over thearguments
object that is given to every function scope.// bad function nope(name, options, arguments) { // ...stuff... } // good function yup(name, options, args) { // ...stuff... }
-
Never use constructor functions for side-effects
// bad new Constructor(); // good var variable = new Constructor();
-
Always chain function calls when possible
// bad var mapped = array.map(mapper), filtered = mapped.filter(filter); filtered.forEach(handler); // good array .map(mapper) .filter(filter) .forEach(handler);
-
Separate function arguments with the space after a comma
// bad function some(first,second,third) { } // good function some(first, second, third) { }
-
Use constructor and prototype to define a module when you need to store local state like this:
'use strict'; var MILE_MULTIPLIER = 0.6214; /** * Creates a new instance of distance descriptor. * @constructor */ function DistanceDescriptor() { // here could be some initialization } DistanceDescriptor.prototype._distance = 0; /** * Sets distance in miles. * @param {Number} distance Distance in miles. */ DistanceDescriptor.prototype.setDistanceInMiles = function (distance) { this._distance = distance / MILE_MULTIPLIER; }; /** * Sets distance in kilometers. * @param {Number} distance Distance in kilometers. */ DistanceDescriptor.prototype.setDistanceInKilometers = function (distance) { this._distance = distance; }; /** * Gets distance in miles. */ DistanceDescriptor.prototype.getDistanceInMiles = function () { return this._distance * MILE_MULTIPLIER; }; /** * Gets distance in kilometers. */ DistanceDescriptor.prototype.getDistanceInKilometers = function () { return this._distance; };
-
Use bind for partial application or to specify
this
inside the method.
-
Use only single quotes for strings
// bad var string = "very bad string"; // good var string = 'this is a good one';
-
Strings longer than 80 characters should be written across multiple lines using string concatenation like this:
// bad var errorMessage = 'This is a super long error that was thrown because of Batman. When you stop to think about how Batman had anything to do with this, you would get nowhere fast.'; // bad var errorMessage = 'This is a super long error that was thrown because \ of Batman. When you stop to think about how Batman had anything to do \ with this, you would get nowhere \ fast.'; // good var errorMessage = 'This is a super long error that was thrown because ' + 'of Batman. When you stop to think about how Batman had anything to do ' + 'with this, you would get nowhere fast.';
-
Always use jsDoc for everything
-
Use one line comments
//
instead/* ... */
// bad /* Some multiline comment */ // good // Some // multiline // comment
-
Use
// TODO:
to annotate solutions or problemsfunction Calculator() { // TODO: total should be configurable by an options param this.total = 0; return this; }
Code style should be checked by:
These tools should be called before tests by command npm test
.