JavaScript namespace utility

23 Aug 2011

Over the past 10 or so years I've written a lot of JavaScript. From very early on, at Caplin Systems, I had to write things in a way which ensured that code was clear, usable, discoverable, reusable, extensible and can easily built upon. One of the concepts that was used was to put code within a namespace. This ensured that you couldn't accidentally override a function in the global window namespace and also meant that the namespace would describe the sort of functionality contained within. I've continued to use this concept in various forms but just realised that I've never actually shared how I do this. So here goes.

It's actually really simple. I've got two functions that I use, and I've recently ported over to the com.pusher namespace since I'm creating demos for my work (and play). The first creates some default namespace objects and then defines a namespace function that can be used from then on to create any other namespace objects.

/**
 * @namespace
 * Top-level namespace to stop namespace clutter.
 */
if(!window["com"]) {
  window["com"] = {};
}

// create pusher ns
if(!com.pusher) {
  com.pusher = {};
}

/**
 * Ensures that a namespace exists.
 * @param {String} namespace The namespace to check for and create if required.
 *
 * @return {Object} The existing or new namespace.
 */
com.pusher.namespace = function(namespace) {
  var parts = namespace.split(".");
  var context = window;
  var nsPath = "";
  for(var i = 0, l = parts.length; i < l; ++i) {
    var name = parts[i];
    if(!context[name]) {
      context[name] = {};
      context[name].__namespace = name;      
    }
    nsPath += name + ".";
    context = context[name];
    if(!context.__namespace) {
      context.__namespace = nsPath.substring(0, nsPath.length-1); // trim off '.'
    }
  }
  return context;
};

A quick example of this might be:

com.pusher.namespace("my.new.namespace");

my.new.namespace.SomeClass = function() {
};
/* define methods etc. */

Then you can access the class anywhere using:

var instance = new my.new.namespace.SomeClass();

The second function that I've only just started to use takes a leaf from node.js. It in that it passes in an exports variable which represents the newly created namespace and then you can add items to that namespace.

Note: I'd previously called the exports variable called export but it would appear this is a reserved word in Safari & Firefox

com.pusher.define = function(namespace, definition) {
  var exports = {};
  definition(exports);

  var nsObject = com.pusher.namespace(namespace);
  for(var thingToexports in exports) {
    nsObject[thingToexports] = exports[thingToexports];
  }
};

You'll noticed that it uses the com.pusher.namespace function to create the namespace object. The usage of this is then as follows:

com.pusher.namespace("my.new.namespace", function(exports) {

  var SomeClass = function() {
  };
  /* define methods etc. */

  exports.SomeClass = SomeClass;
});

The class can then be accessed in the same way as shown previously:

var instance = new my.new.namespace.SomeClass();

I like this last way of doing things as you declare the namespace at the top and wrap everything in a function. You then can pick what you want to expose to the outside world by just adding it to the exports variable.

I'd be interested to hear what you think about this approach. Do you have a better one?