Function decorators in JavaScript

I’ve been looking at how to implement function decorators in JavaScript. The FireFox Sync extension (http://hg.mozilla.org/services/fx-sync) provides a nice implementation. I’m going to describe that implementation in this post.

So let’s assume we have an application with “classes” (constructors and prototypes, really), and we always want the same behavior when exceptions occur in these classes’ methods.

Our classes look like:

MyCtor = function() {};
MyCtor.prototype = {
    method: function(a, b) {
        // do something with a and b
    }
};

The common behavior is implemented at a single place in a decorator function:

var decorators = {
    catch: function(f) {
        return function() {
            try {
                f();
            } catch(e) {
                console.log(e);
            }
        };
    }
};

decorators.catch is the decorator function. It returns a function that executes the decorated function (f) in a try/catch block and logs a message if an exception occurs.

Decorating method with decorators.catch is done as follows:

MyCtor.prototype = {
    method: function(a, b)
        decorators.catch(function() {
            // do something with a and b
        })()
};

method now calls our decorator, and the actual logic of the method
is moved in an anonymous function passed to the decorator. The anonymous function can still access the arguments a and b thanks to the closure.

You may be wondering why decorators.catch delegates the decoration to an inner function as opposed to doing it itself. This is to be able to chain decoration. For example:

 MyCtor.prototype = {
    method: function(a, b)
        decorators.lock(decorators.catch(function() {
            // do something with a and b
        }))()
};

where decorators.lock would be a new decorator of ours.

I guess there are other ways to implement function decorators in JavaScript. I find this one is simple and elegant.

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s


Follow

Get every new post delivered to your Inbox.