Skip to content

Mr.doob's Code Style™

gero3 edited this page Jul 6, 2014 · 25 revisions

JavaScript CodeStyle

General Provisions

  • Code should be in UTF-8.
  • a new line should be LF.
  • Indentation should be tabs.
  • No extra spaces at the end of lines (set up your text editor, so that it removes extra spaces when saving).

Naming

Naming should be as descriptive as possible. The only exception is the indexing variable in an loop. That can be shortened to a single letter starting from i.

  • variableNamesLikeThis
  • functionNamesLikeThis
  • ClassNamesLikeThis
  • methodNamesLikeThis
  • ConstantsLikeThis Private properties and methods of objects begin with an underscore _.

Literals

Objects

  • Object should always be created by {} and not new Object().
  • When creating an empty Object, use {} without spaces.
  • When creating an Object with keys,
    • There should be a single space after the opening bracket.
    • There should be a single space before the closing bracket.
    • Keys should be written without quotes. The exception is when it is nessecary.
    • There should be a space between the key word and the colon.
    • There should be a space between the colon and the value.
    • The comma should have no space before and 1 space behind itself.
    • The last value shouldn't be trailed with a comma.
    • The comma shouldn't start a new line. It should always trail the previous value.

good:

var obj = { A : 1, b : 2, C : 3 };

var obj = { A : 1, 
            b : 2, 
            C : 3 
          };

poor:

var obj = {A : 1, b : 2, C : 3};

var obj = { "A" : 1, "b" : 2, "C" : 3 };

var obj = { A: 1, b: 2, C: 3 };

var obj = { A :1, b :2, C :3 };

var obj = { A : 1 , b : 2 , C : 3 };

var obj = { A : 1, 
            b : 2, 
            C : 3, 
          };


var obj = { A : 1 
          , b : 2
          , C : 3 
          };

Arrays

  • Arrays should always be created by [] and not new Array().
  • When creating an empty Array, use [] without spaces.
  • When creating an Array with values,
    • There should be a single space after the opening bracket.
    • There should be a single space before the closing bracket.
    • The comma should have no space before and 1 space behind itself.
    • The last value shouldn't be trailed with a comma.
    • The comma shouldn't start a new line. It should always trail the previous value.

good:

var arr = [ 1, 2, 3 ];

var arr = [ 1, 
            2, 
            3 
          ];

poor:

var arr = [1, 2, 3];

var arr = [ 1 , 2 , 3 ];

var arr = [ 1, 
            2, 
            3,
          ];

var arr = [ 1
          , 2
          , 3 
          ];

Strings

Strings are written using single quotes or double quotes:

good:

var  lyrics  =  'Never gonna Give you up, Never gonna Let you down' ;
var  lyrics  =  "Never gonna Give you up, Never gonna Let you down" ;

Semicolon

Semicolon are always placed.

Blocks

  • The opening brackets should be followed by 1 new line.
  • The closing brackets should be behind 1 new line.

good:

if ( a === 0 ) {

   //this is good
   return true;

}

poor:

if ( a === 0 ) {
    //this is good
    return true;

}

if ( a === 0 ) {

    //this is good
    return true;
}

if ( a === 0 ) { //this is good

    return true;

}

===============================================================This should still be written

Gaps

Keywords separated by a space: if ( test ) { / / ... }

function foo () { / / ... }

var bar = function () { / / ... }; Before the semicolon no space: return ; Braces

Opening brace is placed on the same line and separated by a space from the previous year: if ( test ) { / / ... }

function foo () { / / ... } Always put braces: Good:

if ( test ) { return ; } Poor:

if ( test ) return ;

if ( test ) return ;

if ( test ) { return ; } Conditional instructions

if

else written on the same line as the closing brace if ( test ) { / / ... } else { / / ... } Assignment in a conditional expression is not used: Good:

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

var foo ; if (( foo = bar ()) > 0 ) { / / ... } Expressions are used only where a value is required: Good:

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

condition && actionIfTrue () | | actionIfFalse (); Long conditions that do not fit on one line, broken down as follows: if ( LongCondition | | anotherLongCondition && yetAnotherLongCondition ) { / / ... } Yoda conditions are used: Good:

if ( getType () === 'Driving' ) {

} Poor:

if ( 'Driving' === getType ()) {

} switch

Switch ( value ) { Case 1 : / / ... Break ;

case  2 : 
    / / ... 
    Break ;

Default : 
    / / ... 
    / / no Break Keyword on the Last Case 

} Cycles

for

As much as possible instead of for use Array.prototype.forEach :

[ 1 , 2 , 3 ]. forEach ( function ( value ) { console . Log ( value ); }); Code using forEach easier to read (it is easier to ignore what is happening in each iteration). Where speed is critical use plain for .

for (var i in obj)

As much as possible instead of for-in used Object.keys :

Object . keys ( obj ). forEach ( function ( Key ) { console . Log ( Key ); }); Operators

with

Operator with not used.

The equality operator

Always use strict equality === (inequality ! == ) if there is no need for typecasting.

Ternary operator

var x = A ? b : C ;

var y = A ? longButSimpleOperandB : longButSimpleOperandC ;

var z = A ? moreComplicatedB : moreComplicatedC ; Unary

All unary operators are written together with the following operands:

var foo = ! bar ; eval

Avoid using eval . To parse json using JSON.parse .

undefined

Check the value through a strict comparison.

Good:

x === undefined ; Poor:

/ / In modern browsers already defined immutable undefined. var undefined ; x === undefined ;

/ / Write more typeof x === 'undefined'

x === void 0 Parentheses

Put, unless it is necessary syntax or semantics. Not used with unary operators delete , typeof and void , as well as the keyword return , throw , New . Exceptions

Create exceptions using New Error :

Good:

throw New Error ( 'msg' ); Poor:

throw 'msg' ; Cast

Use explicit type:

Good:

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

!! foo

  • bar baz + '' ~ []. indexOf ( qux ) Line breaks

The maximum string length of 120 characters if the string goes longer, made ​​possible line breaks with appropriate indents after the transfer. Operators are placed on the previous line: var debt = this . calculateBaseDebt () + this . calculateSharedDebt () + this . calculateDebtPayments () + this . calculateDebtFine (); Closing parenthesis is not pressed against the portability code: Good:

DoSomethingThatRequiresALongFunctionName ( very_long_argument1 , argument2 , argument3 , argument4 ); anotherStatement ; Poor:

DoSomethingThatRequiresALongFunctionName ( very_long_argument1 , argument2 , argument3 , argument4 ); anotherStatement ; Concatenation

String concatenation operator is used + . Design []. join ('') is not used (this was true for older browsers). \ is used. Good:

var foo = 'A string of rather Long English text, an error message' + 'That Actually just Keeps going and going - an error' + 'message to make the Energizer bunny Blush (right through' + 'Those Shades Schwarzenegger)! Where was I? Oh Yes, ' + 'you ' ve Got an error and All the extraneous whitespace is' + 'just Gravy. Have A nice Day. ' ; Poor:

var foo = 'A string of rather Long English text, an error message \ Actually That just Keeps going and going - an error \ message to make the Energizer bunny Blush (right through \ Those Shades Schwarzenegger)! Where was I? Oh Yes, \ you \ 've Got an error and All the extraneous whitespace is \ just Gravy. Have A nice Day. ' ; Blank lines

Can be used to logically group sections of code:

doSomethingTo ( x ); doSomethingElseTo ( x ); andthen ( x );

nowDoSomethingWith ( y );

andNowWith ( z ); this circuit in

We recommend using Function.prototype.bind : doAsync ( function () { this . Fn (); }. bind ( this )); If the function allows you to pass this parameter, use it: Good:

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

[ 1 , 2 , 3 ]. forEach ( function ( n ) { this . Fn ( n ); }. bind ( this )); If you use a variable, call it _this : var _this = this ; doAsync ( function () { _this . Fn (); }); Comments

Comments written in Russian. To use inline comments / / . After / / put 1 space. Comments to the functions, classes, etc. written in the format JSDoc . Functions

Arguments

Choosing the function signature should be avoided Boolean Trap :

/ ** @ param {*} Boolean async

  • / function fetchResults ( async ) {}

/ / On-call function is unclear, which means false. fetchResults ( false ); Use the following methods in order to avoid Boolean Trap:

Split method or function for a few: function fetchResultsSync () {} function fetchResultsAsync () {} Use constants, enumerations or static class field for the parameter values; / ** @ * Enum {Boolean}

  • / var FetchMethod = { SYNC : false , ASYNC : true };

/ ** @ param {*} FetchMethod Method

  • / function fetchResults ( Method ) {}

fetchResults ( FetchMethod . SYNC ); Just avoid Convinience Trap :

/ / Example of WebGL (without documentation are invited to guess what each number means and false) glCtx . vertexAttribPointer ( this . _glHandler , 4 , glCtx . FLOAT , false , 0 , 0 ); From Convinience Trap and Boolean Trap must use named parameters:

/ ** @ param {* Object} params

  • @ param {Boolean} params.async
  • / function fetchResults ( params ) {}

fetchResults ({ async : false });

glCtx . vertexAttribPointer ( this . _glHandler , { size : 4 , type : glCtx . FLOAT , normalizeData : false , stride : 0 , offset : 0 });