- Preface
- Quick Reference
- General Naming
- Specific Naming
- Layout
- Variables
- Objects & Arrays
- Functions & Scope
- Documentation
- Backbone.js
- Require.js
- Files
Any violation of this standard is allowed if it enhances readability or circumvents a considerable performance issue. Make sure to clearly document the differences between the standard and the code as written.
Construct | Convention | Example |
---|---|---|
constant | UPPER_CASE | Speeds.ANIMATION_SPEED |
constructor | CamelCase | ShoppingCartView |
public method | mixedCase | lib.doSomething() |
public var | mixedCase | var firstName; |
- Constructors should be nouns
- Constructors should be named using CamelCase capitalization:
var Product = function(){};
Constants should be placed in a frozen object created as a container for constants, emulating an Enum:
- The enum container should be named using CamelCase capitalization.
- The keys should be named with UPPER_CASE capitalization.
- The constant container should be declaired in the smallest scope possible.
var AnimationSpeeds = Object.freeze({
VERY_SLOW : 2000,
FAST : 700,
VERY_FAST : 100
});
Avoid prefixing private methods or properties with a _
(underscore) character. Code should be refactored to encapsulate private members and prevent them from being exposed. Private members follow the same naming conventions as public members.
// using require.js
define(function(){
var PublicThing, privateMethod;
PublicThing = function(){};
PublicThing.prototype.doSomething = function(){
return privateMethod.call(this);
};
privateMethod = function(){ // NOT _privateMethod
// ...
};
return PublicThing;
});
All names should be written in English.
Names should be as clear as necessary and should avoid unclear shortenings and contractions
var ZumbiniClass; // NOT ZbiniClass
var mouseEventHandler; // NOT mseEvtHdlr
If context can be determined by module/library membership, this context should be used to determine if a member name is clear:
events.Mouse.handler // NOT events.Mouse.mouseEventHandler
Always avoid Hungarian Notation in favor of semantic naming
// incorrect
var Hungarian = function(){
// local variable prefixed with $ to indicate a jQuery object
var $this = $(this);
// property prefixed with it's datatype
this.arrThings = [];
// property prefixed with $ to indicate a jQuery object
this.$elements = $('.elements');
};
// correct
var MuchBetter = function(){
var instance = $(this);
this.things = [];
this.elements = $('.elements');
};
Abbreviations and acronyms should not be UPPERCASE when used as a name:
getHtml(); // NOT getHTML()
JsonView; // NOT JSONView
Names that are methods should be verbs or verb phrases written with mixedCase in the verbSubject format:
lib.doSomething();
lib.get('something');
lib.handleJsonData();
- Boolean variables, properties and methods should be prefexed with
is
,has
,can
orshould
, i.e.lib.isAnimating()
,lib.canAnimate
. - Collections must be plural:
var things = [];
- Variables representing a number of objects should be named
length
, or alternatively include anum
prefix orCount
suffix:var length, numEvents, productCount;
- Iterator variables should be named
i
,j
,k
, etc. - Avoid negated/inverted boolean names:
isNotError, isNotFound
are unacceptable. - Methods that return void should be named after what they do, methods that return an Object should be named after what they return.
- Try to keep lines shorter than 80 characters, and AVOID lines longer than 100 characters. When a statement will not fit on a single line, break it.
- When breaking a line to reduce line length, place the break after an operator, ideally after a comma.
Block layout should be like so:
while (!isDone) {
doSomething();
isDone = moreToDo();
}
if
statements should have the following form:
if (condition) {
statements;
} else if (anotherCondition) {
statements;
} else {
statements;
}
for
statements should have the following form:
var i; // predefined
for (i; condition; update) {
statements;
}
while
statements should have the following form:
while (condition) {
statements;
}
do
... while
statements should have the following form:
do {
statements;
} while (condition);
switch
statements should have the following form:
switch (condition) {
case ABC:
statements;
// fallthrough
case DEF:
statements;
break;
default:
statements;
// no break on the last case -- it's redundant
}
A single statement if else
, while
or for
block must not be written without brackets, but CAN be written on the same line if the line length does not become excessive:
if (condition) { statement; }
while (condition) { statement; }
for (i; condition; update) { statement; }
Code should never rely on Automatic Semicolon Insertion.
Comma seperators, when combined with line breaks, should be used to terminate a line, not start a line:
var correct = {
key1 : 'value', // correct
key2 : 'value'
};
var incorrect = {
key1 : 'value'
, key2 : 'value' // NOT correct
};
Trailing whitespace should be trimmed.
Logical units within a block should be seperated by one blank line:
var doThings = function(obj){
var formattedObject; // space following declaration
formattedObject = getFormattedObject(obj);
formattedObject.moreStuff = true; // space following logical unit
processObject(formattedObject);
};
Whitespace may be used for alignment to enhance readability.
- Tricky or overly complex code should not be commented. It should be rewritten.
- Comments should be written in English.
- Comments should be indented relative to their position in the code.
- Comments should not be included for every single line of code.
Variables should be initialized at the top of the smallest scope possible.
Variables can be declared and assigned a value simultaneously, but only if all variables in the var
statement are treated equally:
var things, moreThings; // correct
var things = [], moreThings = []; // correct
var things = [], moreThings; // NOT correct
Use temporary boolean variables in lieu of complex conditional expressions.
Always test for truth in the if
part of an if else
expression:
if (isAcceptable){ // correct
nominalStatements;
} else {
exceptionalStatements;
}
if (!isAcceptable){ // incorrect
exceptionalStatements;
} else {
nominalStatements;
}
if (!isAcceptable){ // correct, since there is no `else`
}
- Always use
{}
instead ofnew Object()
. - Always use
[]
instead ofnew Array()
.
When possible, use dot notation instead of array notation when accessing an object property:
obj['someKey']; // Array notation
obj.someKey; // Use this instead
The JSON spec enforces quotation marks around object property keys. However, avoid using quoted keys in object literals when possible. Refactor dashes and illegal characters whenever possible to uphold this guideline:
// incorrect
var bad = {
"normalKey" : false,
"dash-key" : false,
"space key" : false
};
// correct
var good = {
normalKey : true,
dashKey : true,
spaceKey : true
};
If possible, try not to mix types in an array:
// bad
var things = [1, "stuff", true];
// good
var things = {
quantity : 1,
name : "stuff",
active : true
};
Remember that Objects and Arrays are assigned/passed by reference, and watch out for gotchas:
// these two variables now point to the same object
var someThings = otherThings = {};
someThings.same = true;
console.log(otherThings.same); // reports true
Constructors, their members, and private methods/variables should be preceeded by a docblock as follows:
define(function(){
var Jedi, Alignments, forceLevel, useTheForce;
/**
* Various Force Alignments
*
* @type Object
*/
Alignments = Object.freeze({
DARK_SIDE : 0,
LIGHT_SIDE : 1
});
/**
* A private variable, global to the Jedi object
*
* @type Number
*/
forceLevel = 100;
/**
* Jedi object
*
* A short description of Jedi
*
* @constructor
* @param ConstructorName injectedObject
*/
var Jedi = function(injectedObject){
statements;
};
/**
* A Static method (notice the lack of `prototype` in the definition)
*
* @param Number level
* @return void
* @static
*/
Jedi.setForceLevel = function(level){
forceLevel = level;
};
/**
* Describing the mindTrick method
*
* @param String target
* @return void
*/
Jedi.prototype.mindTrick = function(target){
useTheForce.call(this, target);
};
/**
* A private method
*
* @param String target
* @return void
*/
useTheForce = function(target){
statements;
};
return Jedi;
});
It is important that comments are kept current. Out-dated comments can make the code hard to read and understand.
Comments should focus on what is not immediately visible. Don't waste time with useless comments like the following:
var i = 0; // Set i to zero.
Avoid in-line javascript.
Logical units (e.g. Modules, Constructors, Libraries, Configuration, Templates, etc.) should always be seperated into individual files containing a single unit.
Configuration files should favor the JSON format and use the .json
extension
/js
/config # JSON files
/libs # First party libraries
/models # Backbone.js models
/vendor # Third party libraries
/views # Backbone.js views