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?