Skip to content

HaveKarma/javascript-styleguide

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 

Repository files navigation

OUT OF DATE - TAKE LOOSELY SINCE WE'RE SWITCHING TO ES6

JavaScript Styleguidea

It's important to write code that is consistent and thus maintainable. Follow these rules.

(formatting and some rules based on https://github.com/aheckmann/js-styleguide)

Tools

Here are some tools I recommend for making your development at Karma better. We use Atom Editor as our main editor and highly recommend it. Here are some helpful plugins:

  • Atom-Beautify - Great way to clean up code that has gotten ugly from people editing with different editors and copypasta!
  • Gist-It - Easy way to share code snippets in Slack. Make sure you set it up to use private gists!
  • Linter - In-line Linting (see next two entries)
  • Linter-jshint - JSHint support for linter
  • Linter-json - JSON Lint support for linter
  • TODO Show - Keep track of all the @TODO and @HACK code spots
    • Settings: TODOs, /TODO:?(.+$)/g, HACK, /HACK:?(.+$)/g
  • Autocomplete Plus - Want your autocomplete to pop up automatically?

Table of Contents

Coding Guide

Tabs or Spaces

Spaces, always. 4 spaces because our monitors are huge.

Line Length

120 characters max. We have giant monitors.

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');

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.

// inconsistant
function eatIceCream() {

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

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

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.

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);
  });
};

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.

Use Strict

Always. No exceptions. At the top of every file

'use strict';

JSHint

All files must pass jshint validation, and it's built into our gruntfile to aid with this.

If you love yourself, you'll install something in your editor to help with this inline.

Rules:

{
    "node": true,
    "browser": true,
    "jquery": true,
    "eqeqeq": true,
    "indent": 4,
    "latedef": true,
    "quotmark": "single",
    "trailing": true,
    "undef": true,
    "unused": true,
    "curly": true,
    "camelcase": true,
    "strict": true
}

Single Quote vs Double Quote

We always use single quotes in JS files because that's what I decided. There doesn't seem to be a winner

(http://stackoverflow.com/questions/242813/when-to-use-double-or-single-quotes-in-javascript)

However, JSON files require double-quotes to be validated, so pure JSON files use double.

Releases

No releases published

Packages

No packages published