Skip to main content

Principles of Writing Consistent, Idiomatic JavaScript.

UPDATE: For a more recent and comprehensive guide, see the Airbnb JavaScript Style Guide.

/*
  Principles of Writing Consistent, Idiomatic JavaScript

  Complete article and examples is here:
    - https://github.com/rwldrn/idiomatic.js
*/

// Conditional Evaluation

// 4.1.1
// When only evaluating that an array has length,
// instead of this:
if ( array.length > 0 ) ...

// ...evaluate truthiness, like this:
if ( array.length ) ...

// 4.1.2
// When only evaluating that an array is empty,
// instead of this:
if ( array.length === 0 ) ...

// ...evaluate truthiness, like this:
if ( !array.length ) ...

// 4.1.3
// When only evaluating that a string is not empty,
// instead of this:
if ( string !== "" ) ...

// ...evaluate truthiness, like this:
if ( string ) ...

// 4.1.4
// When only evaluating that a string _is_ empty,
// instead of this:
if ( string === "" ) ...

// ...evaluate falsy-ness, like this:
if ( !string ) ...

// 4.1.5
// When only evaluating that a reference is true,
// instead of this:
if ( foo === true ) ...

// ...evaluate like you mean it, take advantage of built in capabilities:
if ( foo ) ...

// 4.1.6
// When evaluating that a reference is false,
// instead of this:
if ( foo === false ) ...

// ...use negation to coerce a true evaluation
if ( !foo ) ...

// ...Be careful, this will also match: 0, "", null, undefined, NaN
// If you _MUST_ test for a boolean false, then use
if ( foo === false ) ...

// 4.1.7
// When only evaluating a ref that might be null or undefined, but NOT false, "" or 0,
// instead of this:
if ( foo === null || foo === undefined ) ...

// ...take advantage of == type coercion, like this:
if ( foo == null ) ...

// Remember, using == will match a `null` to BOTH `null` and `undefined`
// but not `false`, "" or 0
null == undefined

// 5.1.1
// A Practical Module

(function( global ) {
  var Module = (function() {

    var data = "secret";

    return {
      // This is some boolean property
      bool: true,

      // Some string value
      string: "a string",
      // An array property
      array: [ 1, 2, 3, 4 ],
      // An object property
      object: {
        lang: "en-Us"
      },
      getData: function() {
        // get the current value of `data`
        return data;
      },
      setData: function( value ) {
        // set the value of `data` and return it
        return ( data = value );
      }
    };
  })();

  // Other things might happen here

  // expose our module to the global object
  global.Module = Module;

})( this );

// 5.2.1
// A Practical Constructor

(function( global ) {

  function Ctor( foo ) {

    this.foo = foo;

    return this;
  }

  Ctor.prototype.getFoo = function() {
    return this.foo;
  };

  Ctor.prototype.setFoo = function( val ) {
    return ( this.foo = val );
  };

  // To call constructor's without `new`, you might do this:
  var ctor = function( foo ) {
    return new Ctor( foo );
  };

  // expose our constructor to the global object
  global.ctor = ctor;

})( this );

// Naming

// A. You are not a human code compiler/compressor, so don't try to be one.

// The following code is an example of egregious naming:

// 6.A.1.1
// Example of code with poor names

function q(s) {
  return document.querySelectorAll(s);
}
var i,a=[],els=q("#foo");
for(i=0;i<els.length;i++){a.push(els[i]);}

// Without a doubt, you've written code like this - hopefully that ends today.

// Here's the same piece of logic, but with kinder, more thoughtful naming
// (and a readable structure):

// 6.A.2.1
// Example of code with improved names

function query( selector ) {
  return document.querySelectorAll( selector );
}

var idx = 0,
  elements = [],
  matches = query("#foo"),
  length = matches.length;

for ( ; idx < length; idx++ ) {
  elements.push( matches[ idx ] );
}

// A few additional naming pointers:

// 6.A.3.1
// Naming strings

// `dog` is a string

// 6.A.3.2
// Naming arrays

// `dogs` is an array of `dog` strings

// 6.A.3.3
// Naming functions, objects, instances, etc

// camelCase; function and var declarations

// 6.A.3.4
// Naming constructors, prototypes, etc.

// PascalCase; constructor function

// 6.A.3.5
// Naming regular expressions

rDesc = //;

// 6.A.3.6
// From the Google Closure Library Style Guide

functionNamesLikeThis;
variableNamesLikeThis;
ConstructorNamesLikeThis;
EnumNamesLikeThis;
methodNamesLikeThis;
SYMBOLIC_CONSTANTS_LIKE_THIS;