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