JavaScript is cool

Category: home/JavaScript
Date: 2013-07-23

I'm writing a lot of JavaScript these days. Sometimes it's really crazy what you can do with that language. I have bunch of tools in my arsenal and I wanted to document them somehow. Writing an article is a good option. By tools I mean patterns, piece of logic or just syntax shortcuts. However, this article is not exactly about design patterns, but it uses some of them. It's just about few ideas, which I came into during my daily scripting.

Let's modulize

We all know that our code should be split in modules. You can't just rely on global objects or functions and build your logic around them. That's why you should be able to write a class and later create instances of it. In JavaScript, that's just a function:

var Class = function() {}
var instance = new Class();

Few words about private variables and methods. Most people think that it's difficult to create such things in JavaScript. Actually it's pretty easy and we are doing it all the time. Everything defined in a closure is actually private, because it is not directly accessible outside the scope of the function. For example:

var Class = function() {
    var pri = "value";
}
var instance = new Class();
console.log(instance.pri);

will outputs undefined. Ok, then how can I go public? If we use the approach above we have to edit the function's prototype. This could happen like that:

var Class = function() {}
Class.prototype.pub = "value";
Class.prototype.pubMethod = function() {
    return this.pub;
}
console.log((new Class()).pubMethod());

Using the prototype chain like that is not exactly compatible with our idea about the private variables/methods. That's because if you want to share a variable between several functions you should define it in the prototype, which makes it public. One of the possible solutions is to put all the logic inside the constructor function.

var Class = function() {
    var pri = "private";
    this.pub = "value";
    this.pubMethod = function() {
        return this.pub + pri;
    }
}
console.log((new Class()).pubMethod());

As you can see pri is private and it is not accessible outside the class, but pubMethod could see it.

However, the usage of this keyword is somehow messy. It's not always clear what you are referring to. That's why I prefer to implement the revealing module pattern.

var Class = function() {
    var pri = "private";
    var pub = "value";
    var pubMethod = function() {
        return pub + pri;
    }
    return {
        pub: pub,
        pubMethod: pubMethod
    }
}
var instance = Class();
console.log(instance.pub, instance.pubMethod());

Notice that we are not using new Class anymore. We actually execute a function, which returns an object. That's how I normally write my modules. There are a lot of benefits of this pattern. One of them is readability. Every time when I wonder what is the API of the class I just check the latest lines.

Extending modules

The trivial extending in JavaScript is done via the function's prototype. Something like that:

function extend(ChildClass, ParentClass) {
    ChildClass.prototype = new ParentClass();
    ChildClass.prototype.constructor = ChildClass;
    ChildClass.prototype.superclass = ParentClass;
}

I'm not dealing with prototypes and I need some other way to handle this. In my case the class's constructor returns a new object every time. It's completely different and I don't have to worry about overwriting or something like that. In theory I can create the object, patch it and return it again. For example:

var Class = function() {
    var pubMethod = function() {
        return "Class";
    }
    return {
        pubMethod: pubMethod,
        pub: "public"
    }
}
var Class2 = function() {
    var parent = Class();
    parent.pubMethod = function() {
        return "Class2";
    }
    return parent;
}
var instance = Class();
var instance2 = Class2();
console.log(instance.pubMethod(), instance2.pubMethod());

The parent variable above contains all the things define in the first version of the class. The big problem with such implementation is that the super class methods are not accessible in their extended versions. I.e. you can't write

parent.pubMethod = function() {
    return parent.pubMethod() + "Class2";
}

You will get Uncaught RangeError: Maximum call stack size exceeded. Of course there are some workarounds, like for example caching the result of pubMethod outside the new closure, but it is still not as nice as I want to be.

The above syntax in Class2 is not looking very good. I used it for a while, but it looks dummy. That's why I wrote a simple function extend for every class which needs to be extended.

var Class = function() {
    var pubMethod = function() {
        return "Class";
    }
    return {
        pubMethod: pubMethod
    }
}
Class.extend = function(f) {
    return function() {
        return f.apply(Class());
    }
}

The calling of Class() returns an object. The newly added extend method simply calls a function within the context of that object. This means that the keyword this in the function passed to extend is actually the object returned by Class. So, we could do the following:

var Class3 = Class.extend(function() {
    return this;
});

And we will get the same object as we call Class(). Even better, we are able to change some of the super class methods.

var Class3 = Class.extend(function() {
    this.pubMethod = function() {
        return "Class3";
    }
    return this;
});

Much better, isn't it? Later we are able to create instances.

var instance3 = Class3();
console.log(instance3.pubMethod()); // outputs "Class3" not "Class"

For me, setting the context of a function with apply or call looks better then prototype liked inheritance. I don't know why, but it's somehow cleaner (at least for me).

Beauty

I'm staying in front of my laptop almost ten hours per day. A big part of that time I spend writing code. If you do the same you know that there is ugly and beautiful code. Seriously, when I see something smart, which works, I enjoy it. For good or bad, JavaScript offers dozen of possible solutions for a specific problem. Very often there is two or more right answers. Nevertheless, some of them are looking better then others. The word beauty just pop up in my mind when I see something cool.

Let's get a simple module written by using the technique above.

var Class = function() {
    var _value = 0;
    var add = function(n) { _value += n; }
    var remove = function(n) { _value -= n; }
    var get = function() { return _value; }
    return {
        add: add,
        remove: remove,
        get: get
    }
}

And a simple use case:

var instance = Class();
instance.add(5);
instance.remove(1);
instance.add(10);
instance.remove(3);
console.log(instance.get()); // result = 11

The first improvement which I'd like to do is to implement a functional chain. jQuery uses this approach:

$("#p1").css("color","red").slideUp(2000).slideDown(2000);

To make this possible, all the methods of our class should return same object. And this object should be the one which we export at the end.

var Class = function() {
    var _value = 0,
        _api = null;
    var add = function(n) {
        _value += n; return _api;
    }
    var remove = function(n) {
        _value -= n; return _api;
    }
    var get = function() {
        return _value;
    }
    return _api = {
        add: add,
        remove: remove,
        get: get
    }
}

Then we will be able to do the following:

var instance = Class();
console.log(instance.add(5).remove(1).add(10).remove(3).get());

That's not bad. However, it could happen even better. What if we modify our class like that so the following syntax is valid:

var result = Class()(5)(-1)(10)(-3)();

Much, much shorter. The idea here is to create a function which returns itself every time. The number and type of the passed arguments is what will matter.

var Class = function() {
    var _value = 0,
        _process = null;
    var add = function(n) {
        _value += n; return _process;
    }
    var remove = function(n) {
        _value -= n; return _process;
    }
    var get = function() {
        return _value;
    }
    return _process = function() {
        if(arguments.length === 0) {
            return get();
        } else if(parseInt(arguments[0]) >= 0) {
            return add(arguments[0]);
        } else {
            return remove(Math.abs(parseInt(arguments[0])));
        }
    }
}

Yes, I know that the example is not so complex and it's just a simple math, but there is a whole library/framework based on this concept - fab.

To make the things a little bit more interesting I wrote a simple html markup generator. I used the same pattern:

var Class = function() {
    var _markup = '',
        _process = null;
    return _process = function() {
        if(arguments.length === 0) { // returning the markup
            return _markup;
        } else {
            var arg = arguments[0];
            if(typeof arg === 'string') { // appending parameter to the markup
                _markup += arg + '\n';
            } else if(typeof arg === 'function') { // execute a function
                var data = arguments[1] || false;
                if(data) {
                    for(var i=0; item=data[i]; i++) {
                        _markup += arg(item);
                    }
                }
            }
        }
        return _process;
    }
}

There is only one function - _process. The method could be called in three different ways:

Then we can use our little generator like that:

var formatLink = function(label) {
    return '<a href="">' + label + '</a>\n';
}
var links = ["home", "about", "contacts"];
var helloWorldSection = 
Class()
    ('<section>')
        ('<h1>')
            ('Hello world')
        ('</h1>')
        ('<p>')
            (formatLink, links)
        ('</p>')
    ('</section>')
();
console.log(helloWorldSection);

The output is:

<section>
<h1>
Hello world
</h1>
<p>
<a href="">home</a>
<a href="">about</a>
<a href="">contacts</a>
</p>
</section>

Communication

It's nice to have everything in modules, but they should communicate somehow. I'm a big fen of the observer pattern. I.e. if I'm interested in something happening in a specific module, I'm simply subscribing to some of its events and wait till the module dispatches something. Here is simple implementation of the observer pattern.

var Class = function() {
    var _listeners = {},
        _api = null;
    var on = function(event, listener) { // subscribing to event
        if(!_listeners[event]) _listeners[event] = [];
        _listeners[event].push(listener);
        return _api;
    }
    var off = function(event, listener) { // unsubscribing
        if(_listeners[event]) {
            for(var i=0; l=_listeners[event][i]; i++) {
                if(l === listener) {
                    _listeners[event].splice(i, 1);
                    break;
                }
            }
        }
        return _api;
    }
    var dispatch = function(event) { // dispatching an event
        if(_listeners[event]) {
            for(var i=0; l=_listeners[event][i]; i++) l();
        }
        return _api;
    }
    return _api = {
        on: on,
        off: off,
        dispatch: dispatch
    }
}

And a simple use case:

var instance = Class(),
    listener = function() {
        console.log("something happens");   
    };
instance.on("something", listener);
// instance.off("something", listener);
instance.dispatch("something");

In most of the cases this works. I mean that's a direct communication between two modules, but sometimes we have much complex situations. For example, we have a module A, which creates instance of module B, which creates instance of module C.

module A -> module B -> module C

Module A is interested in something which happens in module C. In this case, module B should work like a bridge and bypass the event. What if we have a big tree of modules and several nested levels. In such cases I'm using something, which I call event bus. I.e. a central hub which handles the events flow. It's similar like the class above except the fact that it is a singleton:

var EventBus = (function() {
    var _listeners = {},
        _api = null;
    var on = function(event, listener) { ... }
    var off = function(event, listener) { ... }
    var dispatch = function(event) { ... }
    return _api = {
        on: on,
        off: off,
        dispatch: dispatch
    }
})();

Because the EventBus class is a global static class, it is accessible from everywhere.

var ModuleC = function() {
    EventBus.dispatch("something");
    return {};
}
var ModuleB = function() {
    var mC = ModuleC();
    return {};
}
var ModuleA = function() {
    EventBus.on("something", function() {
        console.log("something happen in module C");
    });
    var mB = ModuleB();
    return {};
}
var mA = ModuleA();

The problem of this approach is that if specific event is fired by several modules you should add some logic to identify the dispatcher. Otherwise you can't be sure what is the source of the coming information.

Resolving dependencies

You probably know about requirejs. It's a nice module loader, which resolves dependencies. For example if you need util.js file you should write the following:

require(["helper/util"], function(util) {
    // This function is called when scripts/helper/util.js is loaded.
    // If util.js calls define(), then this function is not fired until
    // util's dependencies have loaded, and the util argument will hold
    // the module value for "helper/util".
});

Keeping every module in separate file is a good idea, but loading them one by one is not the best practice. RequireJS offers something called RequireJS Optimizer, which combines related scripts together into build layers and minifies them. Fairly enough, it solves the problem. But before a couple of months I had a project, which uses Gruntjs for concatenation and minification. And the classes in the application were developed without module.exports or define functionality. The project gets bigger and bigger and I had to think about smarter way to resolve dependencies. To be more specific I needed a function which accepts a module and its dependencies. Again, I decided to use apply and patch the this object inside the module.

Let's take a simple example. We have two classes GuessMyAge and MindReader. The first one returns random number and the second one string.

var GuessMyAge = function() {
    var calc = function() {
        return Math.floor((Math.random()*30)+18);
    }
    return { calc: calc }
}
var MindReader = function() {
    var whoami = function() {
        return 'Dude';
    }
    return { whoami: whoami }
}

There is a module, which wants to use them. Sure, I can add the following:

var Class = function() {
    var age = GuessMyAge(),
        name = MindReader();
}

But, wouldn't it be nice if I just have those two modules inside my function attached to this:

var Class = function() {
    var myAge = this.age.calc(),
        myName = this.name.whoami();
    var message = function() {
        return 'Hello ' + myName + '. You are ' + myAge + ' years old. Am I right?';
    }
    return { message: message }
}
var instance = Class();
console.log(instance.message());

If you combine the two classes with the code above you will get Uncaught TypeError: Cannot call method 'calc' of undefined. That's because age is missing. However, here is the little helper function, which makes the things possible.

var DI = function() { // dependency injection
    if(arguments.length === 2) {
        var Class = arguments[0];
        var dependencies = arguments[1];
        return function() { 
            return Class.apply(dependencies); 
        };
    } else {
        throw new Error("DI requires two parameters.");
    }
}

And the usage:

Class = DI(Class, {
    'age': GuessMyAge(),
    'name': MindReader()
});

So, I'm just describing what Class module needs. Additionally, I'm giving names to the newly created instances. This approach became really flexible, because at some point I needed to replace one of the dependencies with another class. All I did is to change one line - the place where DI helper method is used. For example:

Class = DI(Class, {
    'age': GetMyAgeFromFacebookProfile(),
    'name': MindReader()
});

It is a good practice to define all the dependencies in one place. Just after the modules' definition.

At the end I realize that DI function is the glue which holds the application. That means that I can use it to create a map of the used classes. Kinda cool, isn't it?

Conclusion

Yes, I know that you will say "Why reinventing the wheel?". To be honest, I'll say, "I don't know :)". Maybe, it's because I'm big fen of KISS principle. If there is a way to solve a problem with 10 lines of code, why I should use a whole library. I always dig deeper and deeper to find the best and simple way to achieve my goals. I hope that this article will help you somehow. At least, I'll be glad to see your comment below.


blog comments powered by Disqus