Giter Site home page Giter Site logo

js-styleguide's Introduction

JavaScript Styleguide

We are in the business of maintaining code, therefore we should strive to write code as consistently and maintainable as possible.

Table of Contents

Coding Guide

Tabs or Spaces

Node.js core uses two space indents, so should we.

Line Length

80 characters max.

Whitespace

No trailing whitespace allowed. Clean up after yourself.

Braces

Place opening braces on the same line as the statement.

if (areWeWritingJava)
{
  // hmmmm
}

if (nicelyDone) {
  // ok!
}

Parenthesis

Leave space before and after the parenthesis for if/while/for/catch/switch/do

// inconsistent
if(weAreHavingFun){
  console.log('Wheeee!');
}

// consistent
if (weAreHavingFun) {
  console.log('Wheeee!');
}

Variable and Property Names

Use lower camel case and be descriptive. Aim for one word descriptions if possible.

// inconsistent
var plan_query = model.findById(plan_id);

// consistent
var planQuery = model.findById(planId);

Constructor Names

Constructors should use upper camel case to hint to its intended use.

function Movie(id, title) {
  if (!(this instanceof Movie)) {
    return new Movie(id, title);
  }

  this.id = id;
  this.title = title;
};

var gravity = new Movie(1, 'Gravity');

Named Functions

Name your functions. It aids in comprehension when coming back to it six months later and provides more descriptive stack traces.

model.findOne(params, function(err, doc) {
  // not very helpful
});

model.findOne(params, function userCallback(err, doc) {
  // more helpful
});

Function Spacing

When executing a function, leave no space between it's name and parens.

eatIceCream (); // inconsistent

eatIceCream();  // consistent

Leave a space between your function declaration/expression parenthesis and the opening {.

function eatIceCream(){
  // inconsistent
};

function eatIceCream() {
  // consistent
};

There should be no empty lines between the function name and the first line of code.

// inconsistent
function eatIceCream() {

  var dessert = bowl().of(iceCream);
  human.eat(desert);
}

// consistent
function eatIceCream() {
  var dessert = bowl().of(iceCream);
  human.eat(desert);
}

Ternary Spacing

Break ternarys across multiple indented lines. It's easier to switch the values around when you come back to it later and realize a mistake.

// less maintainable
var docs = Array.isArray(response) ? response : [response];

// more maintainable
var docs = Array.isArray(res)
  ? res
  : [res];

Also, no nested ternary expressions permitted. Business logic is often confusing enough on its own. If necessary, break out the logic into additional if/else blocks.

// do not nest
var msg = first
  ? isValid(thing)
    ? 'ok'
    : 'fail'
  : 'confusing';

// better
var msg = 'not so confusing';

if (first) {
  msg = isValid(thing)
    ? 'ok'
    : 'fail';
}

Semi-colons

Use em.

var semis = function() {
  // codez
}

['property'].forEach(console.log) // TypeError: Cannot call method 'forEach' of undefined
var semis = function() {
  // codez
};   // <--------

['property'].forEach(console.log) // property 0 [ 'property' ]

It's really great if you take the extra time to learn where they're actually necessary, you may just be surprised how few places there are. I personally think it's easier to learn the rules and use them only where they're required, but for even mid-size teams, it's simpler to just use 'em and move on.

Variables

When declaring multiple variables, use "var first" style.

var fix = true;
var nice = 'you best';
var woot = require('woot');

This makes for easier copy/paste later on and less futzing around with semi-colons and commas.

Commas

Use comma first.

// arrays
var array = [
    'my'
  , 'array'
  , 'is'
  , 'neat'
];

// nested arrays
var nestedArray = [
    ['this', 'is', 'a', 'nested', 'array']
  , ['this', 'is', 'too']
];

// objects with on property may be inlined
var simpleObject = { x: 1 };

// objects with more than one property should use comma first
var avgObject = {
    first: 1
  , second: 2
};

// nested objects
var nestedObjects = {
    my: 'object'
  , is: {
        nested: 'indeed'
      , you: 'see'
    }
};

Equality

When comparing a variable against a literal or native type, always place the variable after the equality check.

if (false === myVariable) ..

if ('string' == typeof myVariable) ..

This way we discourage progamming errors due to unintentional assignment.

if (myVariable = false) // oops

if (typeof myVariable = 'string') // oops

References to this

Name variable references to this "self".

Dancer.prototyp.selfie = function selfie() {
  var self = this;
  return function() {
    console.log(self);
  };
};

Errors

If you must throw an error, make sure what you throw is an instance of Error.

For example:

if (!exists) {
  throw 'invalid!'; // not very helpful
}

if (!exists) {
  throw new Error('invalid!'); // more helpful
}

Each instance of Error has a stack property which aids in debugging.

try {
  throw new Error('hmmmm');
} catch (err) {
  console.error(err.stack);
}

Can I throw:

  • strings? nope
  • numbers? no
  • arrays? nadda
  • objects that have a message property? forget it
  • up? please not on me

More context

Same goes for callbacks. If an error condition is identified, pass an instance of Error to the callback.

app.use(function(req, res, next) {
  var err = failedValidation(req)
    ? new Error('could not parse request')
    : undefined;

  next(err);
});

Return Early

Return early whereever you can to reduce nesting and complexity.

function checkSomething(req, res, next) {
  if (req.params.id) {
    if (isValidId(req.params.id)) {
      find(req.params.id, function(err, doc) {
        if (err) return next(err);
        res.render('plan', doc);
      });
    } else {
      next(new Error('bad id'));
    }
  } else {
    next();
  }
};

// return early
function checkSomething(req, res, next) {
  if (!req.params.id) {
    return next();
  }

  if (!isValidId(req.params.id)) {
    return next(new Error('bad id'));
  }

  find(req.params.id, function(err, doc) {
    if (err) return next(err);
    res.render('plan', doc);
  });
};

new is Optional

In constructors, first check if the function was called without the new keyword and correct it if possible by returning a new instance of the constructor and passing along the arguments. This guards against programmer error with negligable downside.

function Script(code) {
  this.code = code;
};

var script = Script('var x = 1');
console.log(script); // undefined

// better
function Script(code) {
  if (!(this instanceof Script)) {
    return new Script(code);
  }

  this.code = code;
};

var script = Script('var x = 1');
console.log(script); // { code: 'var x = 1' }

Inline Documentation

Each function should have corresponding JSDoc-style comments that include parameters and return values. Examples are always appreciated.

/**
 * Adds two numbers.
 *
 * Example
 *
 *     var result = add(39, 12);
 *
 * @param {Number} num1
 * @param {Number} num2
 * @return {Number}
 */

function add(num1, num2) {
  return num1 + num2;
};

Modifying Native Prototypes

Don't do it. It causes debugging headaches, breaks expected behavior and introduces potential incompatibility with new versions of V8. There's always a better way.

// please no
Array.prototype.contains = function(needle) {
  return this.indexOf(needle) > -1;
};

// For example, create a helper module with a function that accepts an array:

// helpers/array.js
exports.contains = function(array, needle) {
  return array.indexOf(needle) > -1;
};

CoffeeScript

Is banned. Just learn JavaScript. Really. Its a simple language.

js-styleguide's People

Contributors

aheckmann avatar clrke avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

js-styleguide's Issues

optional semicolons

Be honest, I don't care about this.

just lines that start with:

(
[
++
/regexp/

spacing around named functions

i find this annoying:

function do (a, b) {

}

since when you call it, you call it as do(a, b) not do (a, b). i'd prefer for it to be consistent.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.