Overview
This library is really just a core set of features which don’t really belong to any particularly category, and I find a handy for common use in all JavaScript I write.
Registering Namespaces
Something that I do a lot of in JavaScript is create namespaces. I always like to keep all code in a single namespace in the same manner which I would do with .NET. But there is a problem, JavaScript doesn’t have namespaces!
I’m sure everyone has written their own code to register namespaces. The code that I use is actually someone I worked with adapted from some code that I’d written as I thought you had to be able to use recursive functions to do it and he was just quicker to getting it written than I was :P.
Usage
The method resides within my core API namespace, slace.core
as a method named registerNamespace
, like so:
slace.core.registerNamespace('some.namespace');
This will create a new namespace starting at the window
object, but it also has the capabilities to add the namespace from any existing namespace, eg:
slace.core.registerNamespace('web', slace);
Now the slace
object will also have web
to go with core
.
Understanding Namespaces in JavaScript
As I mentioned above JavaScript doesn’t have the concept of namespaces, so how do you create a namespace in a language which doesn’t do namespaces?
Well namespaces in JavaScript are actually a bit of a trick, and they aren’t namespaces which are familiar to .NET developers, they are actually just a series of empty objects.
Take this piece of code:
slace.core.registerNamespace('slace.web.controls');
This will produce the following object:
slace = {
web = {
controls = {
}
}
};
Well technically the window
object should be before slace
but it’s skipped for brevity, as is the slace.core
object
So this is really just a set of empty objects!
Looking into the code
So you can find the code here, and let’s have a look at what it does. The crux of it is a recursive function which the namespace is passed into:
slace.core.registerNamespace = function (namespace, global) {
var go;
go = function (object, properties) {
if (properties.length) {
var propertyToDefine = properties.shift();
if (typeof object[propertyToDefine] === 'undefined') {
object[propertyToDefine] = {};
}
go(object[propertyToDefine], properties);
}
};
go(global || (function () { return this; })(), namespace.split('.'));
}
In this function the argument object
is what we’re putting the namespace onto, with properties
is an array of the namespace to define (having been split on the .).
The last line initiates the function and either passes in the object you want to augment, or the object which is scoped as this
for the method (which will be window
unless you’re really going to get nasty with JavaScript, but that’s a topic for another time :P).
Fun fact
This code can actually be reduced by a few lines by making it a self-executing named function (or a self-executing anonymous function if you want ;)), but due to limitations in the Visual Studio 2010 JavaScript intellisense engine it doesn’t work recursively it seems. Odd bug, but easy to get around (and it makes your code a bit more readable!).
Base Extensions
The library also includes some handy extensions for detecting if a method already registered on an object, in the form of Function.method
(which is from Douglas Crockford’s article on JavaScript Inheritance), and the Array.prototype
is also augmented to have Array.contains
, Array.remove
and Array.indexOf
(unless it’s already there).