Wednesday, August 28, 2013

Javascript Namespacing: Object Literal Namespace (OLN) in Javascript

Javascript, unlike many other programming languages does not come with its built-in namespace or class pattern. In many other languages such as Java or C#, the code comes with built-in name-spacing and class patterns. Have a look at C#'s namespace pattern below:
namespace Project
{
    class MyClass
    {

    }
}
You may first ask why do we need a namespace to begin with in a language like Javascript?! As a reply, one can simply say that namespaces avoid the global namespace of your application to become polluted by dividing the global namespace into several manageable chunks of code, calling one another. It is very obvious that if you are writing an application you cannot just continues writing it like this, can you?
var getUserInput = function () {

};

var thenSortIt = function() {

};
If you think you can, you are right! But then you lose track of your functions as it becomes so hard to find your functions in thousands of lines of code and newly added functions. Even if you divide them in separate script files, you still are polluting the global namespace, i.e. as the application starts, you are injecting all the code suddenly inside the browser in one big scope. Do you think that is desirable?! If so, think twice.

The Object Literal Namespace (OLN) pattern, comes with a very easy idea. Wrap your namespace inside a very big object literal:
var myNamespace = {
 instanceVariable: undefined,

 setter: function (element) {
  this.instanceVariable = element; 
 },

 getter: function() {
  return this.instanceVariable;
 },

 randomFunctions: function (message) {
  return "Hello, " + message;
 } 
};
In the following script, that is how you call and interact with you OLN in Javascript:
myNamespace.setter(1000); 

console.log(myNamespace.getter()); //Output: 1000

console.log(myNamespace.randomFunctions("Amir Rahnama!")); //Output: Hello, Amir Rahnama!
One fact to remember here, is that by using OLN as your namespace pattern, there is no level of information hiding in your namespace. You are exposing your whole namespace to the caller's code. Meaning that, you can replace the second line of above with the following line, keeping the output still the same:
console.log(myNamespace.instanceVariable); //Output: 1000
Actually, that is one of the main reasons that many developer dislike OLN namespaces, because they believe in a namespace with public and private values at the same time.

One last thing to note is that you can dynamically extend your OLN Namespace by the following code:
//Dynamically add instance variables to myNamespace
myNamespace.newInstanceVariable = "I am new";

//Dynamically add newFunction to myNamespace
myNamespace.newFunction = function (newMessage) {
 return "Hello Again," + newMessage;
};

And you can guess that you can use them as soon as they are declared:

console.log(myNamespace.newInstanceVariable); //Output: I am new
console.log(myNamespace.newRandomFunction("Mr, Amir Rahnama!")); //Output: Hello Again, Mr. Amir Rahnama!