Skip to content

Instantly share code, notes, and snippets.

@hemanth
Forked from TheJase-Gist/js-best-practices.md
Created March 14, 2012 10:33
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save hemanth/2035645 to your computer and use it in GitHub Desktop.
Save hemanth/2035645 to your computer and use it in GitHub Desktop.
JavaScript best practices

JavaScript Best Practices

Code conventions

Closing/opening brackets

Although this isn't a problem in other languages, because of semicolon insertion, there could be problems if you don't place the bracket on the opening line:

// no:
function()
{
  return  // semicolon inserted here by the engine.  Returns null (not {})
    {
    }  
}

// yes:
function() {  // this semicolon placement doesn't matter, but we should be consistent
  return {
  }
}

CamelCase

JavaScript natives are camelCased, so we should be consistent.

Capitalized Class/Object constructors

Javascript native Object constructors are Capitalized, so we should be consistent.

Feature detection

Feature existence

Check for the existence of a feature before using it:

// no:
navigator.connection;

// yes:
if(navigator.connection) {
  navigator.connection;
}

Run the test only once

If you're going to reuse the feature test, make sure to run it once and cache the result (as Modernizr does). This speeds things up and makes things easier to maintain in the future.

// no:
if(navigator.connection) {}
if(navigator.connection) {}

// yes:
var connection = navigator.connection;
if(connection) {};
if(connection) {};

Define your functions once

Extending native objects

Unless it's a polyfill, generally don't modify objects you didn't create. I.e. Object.prototype

Loops

Cache the length

// no:
var foo = document.getElementsByTagName('p');
for(var i=0; i<foo.length; i++) {};  // hitting the DOM on each iteration

// yes:
var foo = document.getElementsByTagName('p');
for(var i=0, len=foo.length; i<len; i++) {};  // hits the DOM only once

Avoid Array.forEach

Use for/while instead, as it's faster.

Callbacks

Check if a callback is defined and is executable before trying to run it:

// no:
function(callback) {
  callback();
};

// yes:
function(callback) {
  if(callback && typeof callback == 'function') callback();
};

// also yes:
function(callback) {
  callback && typeof callback == 'function' && callback();
};

Unknown variables

If you don't know if a variable is defined:

// no:
foo;   // don't use it before checking if it exists
if(foo);  // if foo isn't defined, it will create a Reference Error
if(foo === undefined) {} // the undefined variable can be overwritten, so avoid it

// yes:
if(typeof foo == 'undefined');
if(window.foo) {} // if foo is a property of another object (in this case the global window)
function(foo) {
  if(foo){};   // ok because foo has been defined in the arguments
}

== vs ===

Triple equals saves a lot of headaches, but you can use == when the possible output doesn't have truthy/falsy problems. For instance, the typeof operator:

if(typeof foo == 'undefined') {}

Named anonymous functions: easier to debug

// no:
(function(){})();

// yes:
(function myFunc(){})();

(note that this is buggy in < IE8)

Liberal use of return (for cleaner code)

// change this:
function() {
  if(foo) {
    fn1();
  } else {
    fn2();
  }
}

// to this:
function() {
  if(foo) {
    fn1();
    return;
  }

  fn2();
}

Shorthand

Use shorthand at your own discretion, but clarity should be valued over brevity. Anyhow, rely on the minifier to make your code short.

Length of variable names

Try to make your variable names semantic and descriptive. Don't make them too short or too long (at your discretion).

// no:
var a = '';  // not descriptive
var getNumberOfSkinCareEligibleItemsWithinTransaction = function() {};  // too long

// yes:
var tag = '';
var eligibleItems = function() {};
for(var i=0; i<10; i++) {};  // variable 'i' is ok because it's a common convention

Ternary

TODO

Branching

// this:
if(somethingExists && fn && typeof fn == 'function') {
  fn();
};

// is equivalent to this:
somethingExists && fn && typeof fn == 'function' && fn();
// this:
if(fn1) {
  fn1();
} else {
  fn2();
}

// is equivalent to this:
fn1() || fn2();

Shorthand object instantiation

// this:
function Person(options) {}
var me = new Person;

// is equivalent to this:
function Person(options) {
  if(!this || this === window) return new Person(options);
}
var me = Person;

See John Resig: Best Practices in Javascript Library Design http://www.youtube.com/watch?v=0LKDImgRfrg#t=32m2s. Above code modified to support ECMAScript 5 strict mode (!this, as strict mode sets 'this' to null and not window by default).

@Aracki
Copy link

Aracki commented Jan 20, 2016

great tips 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment