Friday, August 20, 2010

Creating JavaScript Namespaces

As with any programming language there are many ways to accomplish a task and JavaScript is no different. What I'm about to show you is one way to create namespaces in JavaScript but other approaches exist too.

Organizing functions and variables into classes helps cut down on spaghetti code and introduce some organization to the JavaScript. Namespaces allow you to take that organization a step further and prevent class naming conflicts with other JavaScript libraries.

You can use JSON to create your namespaces but I tend to avoid JSON when creating classes because it does not allow for private members or methods.

The following is an example of how you would create a global namespace object (RootNamespace), add an object to the root object (ServerSideCalls), and then add an even more specific object to the newly added object (Products):

// Our root namespace so that our code does
// not interfere with other libraries.

// Also, being a global object already
// initialized allows calling code to access
// it
without needing to create an instance
// of a class first.
var RootNamespace = new function(){};



// Create a ServerSideCalls object within our
// RootNamespace object

RootNamespace.ServerSideCalls = new function()
{
// Private function
var GetXmlHttpRequestObject = function()
{

if(window.XMLHttpRequest)
{ return new XMLHttpRequest(); }
else if(window.ActiveXObject)
{ return new ActiveXObject("Microsoft.XMLHTTP");
}

}


// Public function
this.SendHttpRequest = function(sURL, sHTTPMethod, sData)
{

// Call the private function to get our
// XmlHttpRequest object

var xhrXmlHttpRequest = GetXmlHttpRequestObject();

// Send the request and return the response
// to the calling function

xhrXmlHttpRequest.open(sHTTPMethod, sURL, false);
xhrXmlHttpRequest.send(sData);
return xhrXmlHttpRequest.responseText;

}
};


// Go a step further and create a Products
// object within our ServerSideCalls object

RootNamespace.ServerSideCalls.Products = new function()
{
this.GetProductList = function()
{

// Call out to our web site to get the
// list of products

var sResult = RootNamespace.ServerSideCalls.SendHttpRequest("ourwebsite.com/products", "GET", "");

// Parse the return data into an array
var arrResults = [];
//...parse code

// Return the array of products
return arrResults;

}
};


Since we initialized our root namespace object when we created it, any code that needs to make use of the contained functions can do so without needing to worry about creating an instance of an object first as in the following example:

function TestNamespace()
{
// Ask for the array of products from our
// web site

var arrProducts = RootNamespace.ServerSideCalls.Products.GetProductList();

// do something with the returned array
// of products

}


You can always create the child namespaces objects within the parent namespace when you create that object. I don’t tend to take that approach because I usually separate my functionality into separate JavaScript files and add the object to the namespace only for the pages that need it.

In this example, I declared the root namespace object as a global variable. I have seen cases where the objects were simply added to the window object and the window object acted like the root namespace. I'm not sure if there are any issues with that approach so I error on the side of caution just in case adding items to the window object is not permitted by a browser in the future.

No comments:

Post a Comment