Javascript Namespace Collisions (and How to Avoid Them)
Writing Javascript to run within web browsers can be a lot of fun! It can also be mind-bendingly painful. I will mention two techniques that can save a lot of heartache when working within a Javascript environment where lots of code is playing (whether that be your own code or code you have pulled in from libraries).
Create Your Own Namespace
First, where is code rooted, by default? Simply enough, it is rooted within the window object. So, a script block like what follows will produce two instances of the same (albeit boring) output.
var a = "Hello world!<br/>";
document.write( a );
document.write( window.a );
So, now we know that everything lives in the window namespace. Not in itself a problem, but imagine that you use a library that creates a global Dog object. It may even create that object behind the scenes and never tell you about it. Now, whomever declares the object last gets to decide what a Dog is, which could have detrimental side effects. Consider the following:
// in library code...
var Dog = {
name: "Fred"
};
function writeDogName() {
document.write( Dog.name );
}
// then in your code...
var Dog = {
speak: function () {
document.write( "Bark!<br/>" );
}
};
writeDogName();
The output from the last line is now undefined since the new Dog object no longer has the name property that the function expects. This means that we need a way to protect both the libraries from our code as well as our code from the libraries we use.
Instead of placing all of our code in the global window namespace, we could create an object that will contain all of our code and variables and act as a namespace for us. Consider the following modification of the previous example in which our code will now be within the SmartVault namespace (object).
// in(considerate) library code...
var Dog = {
name: "Fred"
};
function writeDogName() {
document.write( Dog.name );
}
// in our code, now more encapsulated...
var SmartVault = {};
SmartVault.Dog = {
speak: function () {
document.write( "Bark!<br/>" );
}
};
SmartVault.main = function () {
writeDogName();
};
SmartVault.main();
The code now does what we expect it to do, and we are no longer stepping on a variable that we did not even realize was there to be stepped on. It would have been nice if the library code had been as considerate.
We are still relying on using one name within the window namespace, however. Let us take a step further into namespace independence.
Work Within Your Own (Nested) Scope
This mechanism basically amounts to creating and executing an anonymous function within which all of the variables and functions you will use live. Let us go back to the original example and extend it using this mechanism.
// library code
var Dog = {
name: "Fred"
};
function writeDogName() {
document.write( Dog.name );
}
// our new, scoped code
(function () {
var Dog = {
speak: function () {
document.write( "Bark!<br/>" );
}
};
writeDogName();
})();
Once we create our own anonymous scope, we become free to create just about any construct we like. We then have much less risk of interfering with other code or allowing other code to interfere with us.
Judicious use of these two mechanisms can go a long way into making the Javascript namespace much more manageable. Just ask the jQuery guys!