Anyone working with Javascript for any significant amount of time will probably run into the problem of namespace pollution, where a function (or a whole host of functions) defined in one library override those defined in another. With the proliferation of libraries that extend built in object Prototypes, this problem is extended to the basic behavior of objects acting in ways contrary to what we would expect. When this namespace pollution seeps into library functions and basic objects, it can cause incredibly pernicious problems that are difficult (if not impossible) to track down.
In any significantly useful library or application it’s impossible to completely avoid adding objects and functions to the global namespace, but a structured and sane approach is usually better than seeding objects throughout the global window object. Consider a simple Javascript file that we might load in a page:
var myValue = 42;
function foo() {
alert("Hey there, it's foo.");
}
function bar() {
alert("Hey there, it's bar.");
}
function baz() {
alert("Hey there, it's baz.");
}
Once loaded we can directly access these three functions by name, as they’ve become part of the global namespace. If we were to load another file, with another function named “foo”, “bar”, or “baz”, we’d have a conflict where we attempted to define the same function in the global namespace twice.
A better approach would be to create our own namespace, and store our functions inside of this distinct object. We’d still be extending the global namespace, but only once, for our top level namespace object. This is far from a new idea. Some examples build namespacing using PrototypeJS (or one from Mark Ziesemer), some use the Yahoo API for namespaces. All of these have in common the same basic idea: bring module or package style namespacing familiar from other languages into JavaScript. The module/package structure allows us to create nested sets of classes and objects that can all be accessed from a single base object, so instead of putting all of our functions in the global namespace, as we did above, we could create a different structure to store our functions and data:
com.programmish.values.myValue = 42;
com.programmish.lib.foo = function() {
alert("Hey there, it's foo.");
}
com.programmish.lib.bar = function() {
alert("Hey there, it's bar.");
}
com.programmish.lib.baz = function() {
alert("Hey there, it's baz.");
}
It’s a bit more code to write up front, but now we know our functions (and data) are isolated from other libraries or files we might load. The trick, with all of the namespacing solutions, is creating the namespace object heirarchy; the objects nested within objects. Here’s a simple version, using pure (no external libraries expected) JavaScript:
function N(namespace) {
var pieces = namespace.split('.'), node = window, piece;
while ( piece = pieces.shift() )
node = !node[piece] ? node[piece] = {} : node[piece];
}
Rewriting our example from above using this namespacing function:
// create the 'values' namespace
N('com.programmish.value');
com.programmish.values.myValue = 42;
// create the 'lib' namespace
N('com.programmish.lib');
com.programmish.lib.foo = function() {
alert("Hey there, it's foo.");
}
com.programmish.lib.bar = function() {
alert("Hey there, it's bar.");
}
com.programmish.lib.baz = function() {
alert("Hey there, it's baz.");
}
When we create a new namespace, any existing parts of that namespace that have already been created are left intact, with only new sections of the namespace created. This namespace code compacts nicely to 85 characters, which is plenty small to include in a top level script tag on any page:
function N(n){var p=n.split('.'),b=window,s;while(s=p.shift())b=!b[s]?b[s]={}:b[s];}
So please, use some form of JavaScript namespacing.
You might want to try Object Literal instead of what you are suggesting here.
The Object Literal form mixes well with namespacing. I skipped over the literal form in favor of a simple example, but there is a point at which the literal form becomes unwieldy without some additional structure. In a small enough file the literal form functionally acts as namespacing, adding only a single top level window object. The benefit of namespacing, when the quantity of code grows or is spread across multiple files, is in the construction of the object hierarchy without regard to what order files are loaded or which portions of the hierarchy already exist.