One of the first things you learn programming in JavaScript is, "Global variables are evil." This is especially true when writing a JavaScript library, but I'd take that advise even otherwise to avoid unnecessary headaches.

As an avid jQuery user, one thing I do in almost every project is define a namespace function on the jQuery object.

jQuery.namespace = function(ns, obj) {
	var ns = ns.split('.'), 
		p = window,
		i;
	for(i=0; i<ns.length; i++) 
		p = p[ns[i]] = p[ns[i]] || {};
	if (obj) 
		jQuery.extend(p, jQuery.isFunction(obj) ? obj(p) : obj);
};

This function will take in either an object or a function that takes in an object, then create the namespace or extend it if it exists.

// Example 1
$.namespace('foo.bar', {
	myVar: 1, myOtherVar: 2, someFunction: function() { alert(this.myVar + ',' + this.myOtherVar); }
});
foo.bar.someFunction();
//--> alerts "1,2"

// Example 2
$.namespace('faz', { baz: { a: 1, b: 2 } });
$.namespace('faz.baz', function(old /* previous namespace */) {
	old.a = 'new value'; // change previous assignment of a
	old.printMe = function() { alert(old.a + ',' + old.b); };
});
faz.baz.printMe();
//--> alerts "new value,2"

The second example shows a case where an function is passed instead of an object. This is useful for many reasons which I won't get into... actually you can read a great post here about JavaScript module patterns.

And when jQuery isn't being used on a project, the following does the exact same.

function namespace(ns, obj) {
	var ns = ns.split('.'), 
		p = window,
		i, k;
	for(i=0; i<ns.length; i++) 
		p = p[ns[i]] = p[ns[i]] || {};
	if (obj) {
		obj = obj instanceof Function ? obj(p) : obj;
		for (k in obj) {
			if (obj.hasOwnProperty(k))
				p[k] = obj[k];
		}
	}
}


blog comments powered by Disqus