Coding Javascript as Javascript

One of the most common questions that I hear at companies I’ve worked at and classes I’ve taught is, “Why don’t you write Javascript as if it’s ____ language?” Fill in the blank as you like.

The question I immediately ask is: “do you enjoy writing Javascript? Is it a fun language to code in?” The answer is invariably a strong “no!”

Javascript, for all its flaws (which are not few), is one of the most flexible programming languages ever created. It is a new type of language which is neither procedural nor class-based OOP, but can mimic both if you work hard at it. I don’t mean that it’s prototypal; that’s just one feature, and quite possibly the most misused one. I mean that it’s expressive.

Any object can be extended with any behaviour at any time, and that behaviour can be called at any time. You can write objects which aren’t classes, but groups of behaviours, and extend any other object with them when you need. Even JSON data coming in from a server can instantly be embedded with such behaviour.

Mimicking another language with Javascript is not only hard work, but will cause the author to lose the advantages of the new type of language (which, frankly, are fun when you get the hang of them!) There’s no need in Javascript for complicated class hierarchies to create a stable, maintainable body of behaviour in even the largest applications. Javascript, used properly and not as if it were another language, can create libraries and applications written in a tiny fraction of the number of lines that a classical OOP model requires. Fewer lines means less code to maintain, and less code for new team members to learn.

Do note that, due to the newness and, ironically, the flexibility of the language, these different patterns are still being developed. It’s hard for all of us to let go of old ideas and fully embrace the new ones, and deadlines often mean not doing that new feature in the way you’ve been learning (or brainstorming). Ultimately, you and the developers who follow after you (and ultimately the company) will pay the price for such shortcuts.

Caveats of the JS Module Pattern

Javascript modules are a nifty construct which I was lucky enough to learn firsthand from Douglas Crockford in his (then) small classes at Yahoo c2005. He didn’t use the term “module pattern” then — I expect he hadn’t thought of the phrase yet. It was just a way to have private variables and methods.

I still love them, but I have some caveats with regards to using them for non-singleton objects.

First, what is a module?

var counter = function(){
    var my = {
        count: 0,
        max: 5,
        isPastMax: function(){
            return this.count > this.max;
        }
    };
    //This is what gets assigned to the variable "counter"
    return {
        getCount: function(){
            return my.count;
        },
        reset: function(){
            my.count = 0;
        },
        increment: function(){
            my.count++;
            if (my.isPastMax()) {
                this.reset();
            }
        }
    };
}(); //NOTE the (). That makes the outer function run and return immediately

A module is nothing more than a function which returns a public API object which, through the magic of closure, has access to truly private methods and variables. Here I’ve put them all as properties of private variable my.

counter is now a singleton object that maintains a counter state privately. No more methods can be added to it which reach anything in my that we haven’t explicitly allowed.

This is all well and good. But what if we want more than one counter? Let’s take off the trailing () so that we have a factory that produces counters:

var Counter = function(){
   //just as above
}; //NOTE the absence of ()!
var instances = [];
for (var i=0; i<100; i++) {
    instances.push(Counter());
}

Now we have 100 instances of the Counter module!

Unfortunately, the encapsulation has come with a price in this case. Every function we defined within Counter has to be created again and occupy more memory!

Sometimes this is acceptable, if the number to be created is low and the module is small. If you’ve got a module that goes on for a few pages and you intend to make a few dozen instances, expect to be eating up substantially more memory than a similar feature using a non-encapsulated object, like so:

var Counter = {
    _count: 0,
    _max: 5,
    _isPastMax: function(){
        return this._count > this._max;
    },
    reset: function(){
        this._count = 0;
    },
    increment: function(){
        this._count++;
    },
    getCount: function(){
        return this._count;
    }
};
Object.extend = Object.extend || function(a, b){
    for (var k in b) {
        if (b.hasOwnProperty(k)) { a[k] = b[k]; }
    }
    return a;
};
var instances = [];
for (var i=0; i<100; i++) {
    instances.push(
        Object.extend({}, Counter)
    );
}

All of the functions exist only once in memory, referenced by the individual instance objects.

Make no doubt: the module pattern is a tool that every good Javascript developer should understand. It provides excellent encapsulation that can’t be externally broken. It’s not without its drawbacks, however.