How I like my JavaScript

I like JavaScript alot.

I do not however like most of the JavaScript that I see, I am not talking about libraries or pure JavaScript projects I come across in Github. What I am referring to here is the JavaScript that is written to add small amounts of interactivity to modern websites; the most common use for JavaScript.

As it is often used for small things such as submitting a checkbox state change to update the server, performing a simple calculation or displaying a dialog box I think it is often overlooked and not given the same amount of care and thought as the rest of the application.

The focus of this post is particularly on organising the JavaScript in projects where it does not play a key role and subsequently in promoting reuse, consistency of convention and accessibility of the code that does get written. I am not pretending to be an expert on the topic but I would like to share some of the things I do - to try and achieve these - with what I think is very little effort input.

The 2 most common ways I see JavaScript being used are

  • A single huge application.js or equivalent with a document ready function that reads initially a hundred or so lines and at the end of the project often thousands of lines.

  • Multiple JS files named after the controller that they relate to. Rails creates one of these for you automatically if you are using the controller generator. Each of these will have a document ready function filled with bindings mainly.

The problems that arise from these two common practises are often shared and include

  • Not knowing where to add a piece of code that should be shared across the application.

    The sorting functionality that was written for users could also be used for news articles, but where does that go? On the line 1355 of app.js next to the user sorting? In the users.js where it already exists for users and we can then use it for both? In news.js as copy paste from users.js?

  • Forgetting/not being able to find a piece of code that already does what you want with a small refactor. This usually follows from what happens above, we end up adding code to where similar code exists or reusing bits of code poorly

  • and finally finding out what in fact does take place when the application is loaded

    As much as I hate duplication of code or trying to figure out where to add a piece of code so it fits in with how rest of the project has been writen, this is the worst part, especially when the document ready function is literally thousands of lines long with bindings and inline functions for them.

Having struggled with these issues for a long time I found a good start to a solution I really liked in Addy Osmani's excellent free Learning JavaScript Design Patterns book that you can read on his website.

The following snippet is a combination of techniques from that book but mostly it all revolves around the Revealing Module Pattern

// modules/sorting.js
var PROJECT = window.PROJECT || {};

PROJECT.sorting = function () {

  function sort_table() {
    // some sorting code...
  }

  function init() {
    $("table.sortable").on("click", "td.sort", sort_table);
  }   

  return {
    init: init
  };
}();

Lovely. If you are not entirely sure what the above does I would recommend you have a look at the Module Pattern and Revealing Module Pattern chapters of Addy Osmani's book.

Here's a quick run through of some of the more important features

  • The file name and location: the module lives inside the modules directory, keeping it separate from third party plugins or libraries. The name of the file matches that of the module which is very descriptive of its function.

    By doing this you make creation of search and sorting modules as easy as users or news modules.

  • Check to see whether the namespace has already been declared and use it, if not create it. This is something I very much like about this; the namespacing!

    We all know polluting the global namespace is bad for various reasons and I honestly believe there is no real reason for most applications to assign more than a single object to the global namespace.

  • init() function which performs tasks the module needs to accomplish to provide functionality or set itself up to be useful. Note this is also included in the returned object from the module creation making this function public.

  • The binding done inside the init function does not include the functionality. Rather it only refers to the function which contains the code to perform the action.

    This keeps the init function small and easy to read. Usually it will end up being a short list of bindings to various functions within that module, they should be easy to read through to find out what elements are bound to by this module and if further information is required as to what those bindings do the function code can then be read.

Now this is all fine and well but if you include this file it doesn't actually do what it is supposed to. The final piece of the puzzle is the main js file

// application.js
$(function () {
  PROJECT.sorting.init();
  PROJECT.search.init();
  // etc
});

What this provides you with is a single document ready function which in turns asks all the relevant modules to initialise themselves and in an order that is easy for you to change if need ever arises.

It allows for you to quickly disable and re-enable entire modules by commenting out a single corresponding init line when investigating a problem or debugging and I think it also promotes good naming conventions.

This is by no means a perfect solution but for the small amount of effort and sheer simplicity I think it establishes a nice convention to follow throughout even larger projects.

I hope this post helps you tame some of the problems detailed above if you are experiencing them or at the very least provides you with some food for thought.

Let me know what your thoughts are either via email [fxn at fxndev dot com] or on twitter @efexen