JavaScript in the small


My most recent project was on a fairly typical Java Web project where we had a component that should be written in JavaScript. Nothing fancy, and nothing big. It does seem like people are still not taking JavaScript seriously in these kind of environments. So I wanted to take a few minutes and talk about how we developed JavaScript on this project. The kind of advice I’ll be giving here is well suited for web projects with small to medium amounts of JavaScript. If you’re writing large parts of your application on the client side, you probably want to go with a full stack framework to help you out, so these things are less relevant.

Of course, most if not all things I’ll cover here can be gleaned from other sources, and probably better. And if you’re an experienced JavaScript developer, you are probably fine without this article.

I had to do two things to get efficient in using JavaScript. The first one was to learn to ignore the syntax. The syntax is clunky and definitely gets in the way. But with the right habits (such as having a shortcut for function/lambda literals, and making sure to always put the returned value on the same line as the return statement) I’ve been able to see through the syntax and basically use JavaScript in a Scheme-like style. The second thing is to completely ignore the object system. I use a lot of object literals, but not really any constructors or the this-keyword. Both of these features can be used well, but they are also very clunky, and hard to get everyone on a team to understand the same way. I love prototype based OO as a model, and I’ve used it with success in Ioke and Seph. But with JavaScript I generally shy away from it.

The module pattern

The basic idea of the module pattern is that you encapsulate all your code in anonymous functions that are then immediately evaluated to generate the actual top level object. Since JavaScript has some unfortunate problems with global variables (like, they are there), it’s safest to just put all your code inside of one or more of these modules. You can also make your modules take the dependencies you want to use. A simple module might look like this:

var olaBiniSeriousBanking = (function() {
  var balance = 0;

  function deposit(num) {
    balance += num;
  }

  function checkOverdraft(amount) {
    if(balance - amount < 0) {
      throw "Can't withdraw more than exists in account";
    }
  }

  function withdraw(amount) {
    checkOverdraft(amount);
    balance -= amount;
  }

  return {deposit: deposit, withdraw: withdraw};
})();
In this case the balance variable is completely hidden inside a lexical closure, and can only be accessed by the deposit and withdraw functions. These functions are also not in the global namespace so there is no risk for clobbering. It’s also possible to have lots and lots of helper functions that no one else can see. That makes it easier to make your functions smaller – and incidentally, the largest problem I’ve seen with JavaScript code quality is that functions tend to be very large. Don’t do that!
A useful variation of the module pattern is to extract the construction function and give it a name. Even though you might use it immediately, it makes it possible to create more than one of these, use different dependencies, or make it accessible from tests so you can inject collaborators:

var olaBiniGreeterModule = (function(greeting) {
  return {greet: function(name) {
    console.log(greeting + ", " + name);
  }};
});
var olaBiniGreeterEng = olaBiniGreeterModule("Hello");
var olaBiniGreeterSwe = olaBiniGreeterModule("Hejsan");

RequireJS

The module pattern is good on its own, but there are some things that can be done by a loader that makes things even better. There are several variations of these module loaders, but my favorite so far is RequireJS. I have several reasons for this, but the main one is probably that it is very light weight, and is actually a net win even for very small web applications. There are lots of benefits with letting RequireJS handle your modules. The main ones is that it takes care of dependencies between modules, and loads them automatically. This means you can define one single entry point for your JavaScript, and RequireJS makes sure to load everything else. Another good aspect of RequireJS is that it allows you to avoid any global names at all. Everything is handled by callbacks inside of RequireJS. So how does it look? Well, a simple module with a dependency can look like this:

// in file foo.js
require(["bar", "quux"], function(bar, quux) {
  return {doSomething: function() { 
    return bar.something() + quux.something();
  }};
});
If you have something else that uses foo, then this file will be loaded, bar.js and quux.js will be loaded and the results of loading them (the return value from the module function) will be sent in as arguments to the function that creates the foo module. So RequireJS takes care of all this loading. But how do you kick it off? Well, you should have one single script tag in your HTML, that will point to require.js. You will also add an extra attribute to this script tag that points to the entry point to the JavaScript:

<script data-main="scripts/main" src="scripts/require.js"> </script>
This will do a number of things. It will load require.js. It will set the scripts directory as the base for all module references in your JavaScript. And it will load scripts/main.js as if it’s a RequireJS module. And if you want to use our foo-module earlier, you can create a main.js that looks like this:

// in file main.js
require(["foo"], function(foo) {
  require.ready(function() {
    console.log(foo.doSomething());
  });
});
This will make sure that foo.js and its dependencies bar.js and quux.js will be loaded before the function is invoked. However, one aspect of JavaScript that people sometimes gets wrong is that you have to wait until the DOM is ready to execute JavaScript. With RequireJS we use the ready function inside the require object to make sure we can do something when everything is ready. Your main module should always wait with doing something until the document is ready.
In general, RequireJS has helped a lot with structure and dependencies and it makes it very simple to break up JavaScript into much smaller pieces. I like it a lot. There are a few downsides, though. Main is that it doesn’t interact well with server side JavaScript (or at least it didn’t when I read up on it a month ago). Also, it doesn’t provide a clean way of getting access to the module functions without executing them, which becomes annoying when testing these things. I’ll talk a bit more about that in the section on testing.

No JavaScript in HTML

I don’t want any JavaScript whatsoever in the HTML, if I can avoid it. The only script tag should be the one that starts your module and loading framework – in my case RequireJS. We don’t have any event handlers embedded in the pages at all. We started out from a place where some of our pages had lots of event handlers and refactored to a much smaller code base that was much easier to work with by extracting all of these things into separate JavaScript modules. This has a side effect that anything you want to work with should be possible to semantically identify, either by using CSS classes or data attributes. Try to avoid convoluted paths to find elements. It’s OK to add some extra classes and attributes to make your JavaScript clean and simple.

Init functions on ready

In terms of how we structure modules in a real application, we don’t actually do much work on startup. Instead, most of the work involves setting up event handlers and so on. The way we are doing that is to have the top level modules expose an init method, that is expected to be called by the main module when it starts up. Imagine in a system where you have dojo as the main framework, and you have this code:

// foo.js
require(["bar"], function(bar) {
  function sayHello(node) {
    console.log("hello " + node);
  }

  function attachEventHandlers(dom) {
    dom.query(".fluxCapacitors").onclick(sayHello);
  }

  function init(dom) {
    bar.init(dom);
    attachEventHandlers(dom);
  }

  return {init: init};
});

// main.js
require(["foo"], function(foo) {
  require.ready(function() {
    foo.init(dojo);
  });
});
This will make sure to set up all event handlers and put the application in the right state to be used.

Lots of callbacks

Once you’ve taught yourself to ignore the verbosity of anonymous lambdas in JavaScript, they become very handy tools for creating APIs and helper functions. In general, the code we write use a lot of callbacks and helper wrapper functions. I also use functions that generate new functions quite liberally, doing things like currying and similar aspects. A fairly typical example is something like this:

function checkForChangesOn(node) {
  return function() {
    if(dojo.query(node).length() > 42) {
      console.log("Warning, flux reactor in flax");
    }
  };
}

dojo.query(".clixies").onclick(checkForChangesOn(".fluxes"));
dojo.query(".moxies").onclick(checkForChangesOn(".flexes"));
This kind of abstraction can lead to very readable and clean JavaScript if done well. It can also lead to code where very piece is as small as it can be. In fact, one of the ways we use to make the syntax a little bit more bearable is to extract creation of anonymous functions into factory functions like this.

Lots of anonymous objects

Anonymous objects are great for many things. They work as a substitute for named arguments, and can be very useful to return more than one value. In our code base we use anonymous objects a lot, and it definitely helps with code readability.

Testing

We use Jasmine for unit testing our JavaScript. This works quite well in general. Since this is a fairly typical Java web application we wanted to run it as part of our regular build process. This means we ended up using the JUnit Jasmine runner, which allow us to run these tests outside of browsers and format the results using all the available JUnit tools. Since we’ve tried to make the scripts as modular and small as possible, and also extracting most of the DOM behavior, we have avoided using HTML fixtures. This means our tests are leaning more towards traditional unit tests, rather than BDD style tests – which I’m not sure I’m comfortable with. But with the current size of the application, this is not really a problem.
Seeing as we wanted to test each module in isolation, we wanted to be able to instantiate the RequireJS module with our custom mock dependencies. This ended up not being very easy with RequireJS, so instead of trying to fit in to that model, we just don’t load RequireJS at all during testing, but instead have a top-level require function that just saves away the module function with a well defined name. This means we can instantiate the modules as many times as we want and inject different mocks for different purposes.
In general, Jasmine works well for us, but there are some features missing from the mocking/stubbing framework that makes certain things a bit complicated. One thing I miss a lot is the capability of having stubs returning different valueus depending on the arguments sent in. Some ugly code has been written to get around this.

Open questions

Our current JavaScript process works well for us, but there are still some open things we haven’t done yet. First among these is to integrate JSLint into our build process. I really think that should be there, so I have no excuse. We don’t have tests running inside of browsers. I’m actually OK with this, since we’re trying to do more unit level coverage with Jasmine. Hopefully our acceptance tests cover some of the browser based testing. We are not doing minification at all, and we probably won’t need it based on the current expected usage. For a different audience we would certainly minify everything – this is something RequireJS can do really well though. We don’t have any coverage tool running on our JavaScript either. This is something I’m also uncomfortable with, but I haven’t really found a good tool that allows us to run coverage as part of our CI process yet. I also care more about branch coverage than line coverage, and no tool seems to give you this at the moment.

Summary

JavaScript can be completely OK to work with, provided you treat it as a real language. It’s quite powerful, but we also have a lot of bad habits based on hacking together small things, or just doing what works. As we go forward with JavaScript, this needs to stop. But the good news is that if you’re a decent developer, you shouldn’t have any problem picking anything of this up.

29 Comments, Comment or Ping

  1. Tom C

    Nice write-up.

    I also came to Javascript via more structured languages. I gravitated towards Dojo because it felt a little less hackish.

    The new 1.7 module loader stuff that you reference is an incredibly powerful system. I’m not sure if you’ve seen it yet, but there are some nice event handling modifications in 1.7 also.

    /blog/2011/08/03/dojoon-new-event-handling-system-for-dojo/

    October 25th, 2011

  2. Nice article!

    Oh, there’s an error on your bank example. The function checkOverdraft should be named checkOverdraw instead. ;)

    October 25th, 2011

  3. Nando: Not to quibble, but the correct term is actually overdraft. When an overdraft happens, the account is said to be overdrawn.

    October 25th, 2011

  4. Oh, what I meant is that you declared it as checkOverdraft but it’s calling it as checkOverdraw. Sorry for the confusion. I’m not into financial jargon on English language. :)

    October 26th, 2011

  5. Nice writeup. Most of my non-backbone apps definitely look similar to what you’re describing.

    Since you’re on Java, one alternative way to run Jasmine specs is my jasmine-maven-plugin:

    /jasmine-maven-plugin

    The maven plugin is obviously only helpful if you’re using Maven to build, but it allows you to run the specs headlessly (using HTMLUnit as opposed to env.js, but I’m looking at making it pluggable to support the webkit widget) as well as in a browser. It also generates JUnit XML reports, if you’re into that sort of thing.

    Finally, as for your JSLint point I’ve been integrating JSHint in my build by using a fancy Jasmine spec for it. I’m sure you could accomplish something similar: /1039164

    October 26th, 2011

  6. Have you tried jasmine-stealth?

    /searls/jasmine-stealth

    October 26th, 2011

  7. Magnus: jasmine-stealth looks exactly like what I need! =)

    Justin: Thanks for the pointers – we are currently not using Maven, but the Jasmine JUnit runner runs with Rhino, which works fine for our purposes.

    Nando: Oh, thanks, I’ve updated the example. (Sorry for the confusion.)

    October 26th, 2011

  8. LOL, thanks Magnus. I recommend two unnecessary things I wrote and then you reply with the one thing I wrote that he actually needed :-P

    October 26th, 2011

  9. Nice write-up, thanks for guiding non-JS devs to a better experience, I’be been using RequireJS since last year and it was indeed a huge improvement on my workflow… I have a few comments about the post tho..

    You just need to wait for DOM ready if the code you are trying to run needs the DOM to execute (add event listeners, add/remove elements, etc..), a lot of setup work can be done before DOM ready.. if the script was loaded at the bottom of the HTML (just before closing the body tag) there is no need to wait for DOM ready.

    Addy Osmani just published an article about modular JavaScript (/writing-modular-js/) which includes more explanation about the AMD module format (used by RequireJS and Dojo 1.6+).

    About not using inheritance and the `this` keyword: /post/4731036392/evolution-of-a-prototypal-language-user – remember that composition > inheritance…

    Code written in the AMD format can be executed on node.js by using r.js (/docs/node.html).

    About testing… You can use the RequireJS paths config to create alias that points to mock objects (/docs/api.html#config) or you could use the factory! plugin (which I haven’t tried yet): /tigbro/requirejs-factory-plugin

    A highly recommended book about JavaScript for people who already know how to program other languages is Javacript Patterns by Stoyan Stefanov (/JavaScript-Patterns-Stoyan-Stefanov/dp/0596806752), after you understand how it works it becomes a great language to work with.

    Cheers.

    October 26th, 2011

  10. Dan Fabulich

    require.js can have a very negative impact on client-side performance. If Main depends on Foo, and Foo depends on Bar, you’ll have to do four round trip requests in serial to get Bar. First you load Require.js, then Require.js loads Main. Only then does Require know that it should begin downloading Foo, and only at the end can Require know to start downloading Bar.

    On IE8+, you’re better off just including the tags directly at the end of the body of your HTML, so all scripts can begin downloading in parallel. Alternately, create a JS rollup so everything downloads in one script file.

    October 26th, 2011

  11. Hi Ola,

    I just had some similar thoughts to yours this very morning.

    /2011/10/26/javascript-model-view-controller-example/

    Though I like your description of things much better.

    Thanks for sharing.

    Jonathan

    October 26th, 2011

  12. Jonas Claesson

    I’ve used the module pattern but found some issues with it that required some tweaking. First of all, you are basically creating a singleton class that gets instantiated when you include the .js file (which makes it a bit harder to test). Since its get executed when you include the file, you now have to worry about the order in which you include your .js files

    I’ve found the better way to do it is this:

    var BankController = function(pModel) {

    var model = pModel || new BankModel();

    function deposit(num) {
    model.deposit(num);
    }

    / …. /

    return {deposit: deposit, withdraw: withdraw};
    });

    then you can easily test it like this:

    new BankController(modelMock).deposit(10);

    My good colleague Jonathan, wrote a blog about this:
    /2011/10/26/javascript-model-view-controller-example/

    Another thing to keep in mind is, if performance is an issue, the prototype way of defining classes, will be a clear winner, since it doesn’t duplicate every function for every instance…

    cheers,
    @jonasingvar

    October 26th, 2011

  13. Dan: you are right, except that doesn’t apply when you do minification, where RequireJS will make sure all files are collapsed into one, based on the dependencies specified. And if performance is an issue, minification is usually a good first step (and I mention that in the end of the article)

    October 26th, 2011

  14. Erik Bakstad

    I highly recommend using sinon.js (/) + jasmine-sinon (/froots/jasmine-sinon) for mocking.

    October 27th, 2011

  15. Huey P

    I’ve only written a few small things with JS, but I have treated it as OO, not really scheme-like. I like what you show here and would like to try treating it as scheme-like. I do have a few questions though.

    You seem to reference dojo in more than skin deep places, for instance in checkForChangesOn(node). I was under the impression it is a good idea to hide that stuff behind some kind of view object. Instead are you okay using it in more places because you can stub/mock it? For instance in your init example (foo.js) you pass dojo in and refer to it via dom so it should be easily stub/mockable? Or is that for other reasons?

    I don’t know why but I just worry about having selectors all over like that. Is that un-needed worry on my part?

    October 27th, 2011

  16. Kris Read

    Ola, what do you think about dojo? I agree with everything you’ve said except the top comment about ignoring the object system, although it’s interesting to think about reading code that totally omits using it.

    October 27th, 2011

  17. Did you consider CoffeeScript?

    October 27th, 2011

  18. Alex Fritze

    Hi Ola,
    when you get tired of the callbacks and want to see a different take on how to orchestrate concurrent stuff in JS, check out Stratified JavaScript ( http://stratifiedjs.org ). You might remember it from the Emerging Languages workshop at OSCON last year.

    October 27th, 2011

  19. Hi Ola,

    Thanks for write up, its really informative and useful. Regarding testing, I would like to ask one question. We are using JSTestDriver with Jasmine and found that it works well and its really fast too. Jasmine has an adapter for JSTd. /ibolmo/jasmine-jstd-adapter
    Do you have any comments on JSTestdriver? One advantage I found with JSTd is that it runs in browser really fast.

    Thanks,
    Leena

    October 28th, 2011

  20. JsMockito works really well for mocking. Not sure why you aren’t using it with Jasmine.

    October 31st, 2011

  21. Great article. Thanks for sharing. And don’t forget those vars! /post/12175941935/how-one-missing-var-ruined-our-launch

    November 1st, 2011

Reply to “JavaScript in the small”