Friday, January 31, 2014

Namespaces in Javascript

Namespacing in Javascript can be achieved in following ways

1. Single global variables
2. Prefix namespacing
3. Object literal notation
4. Nested namespacing
5. Immediately-invoked Function
6. Expressions
7. Namespace injection

Lets go in detail..

Single Global Variables:
Here we define a single Global variable which holds all methods and properties of object.

Ex.
var myExApplication =  (function () { 
        function(){
            //...
        },
        return{
            //...
        }
})();

Disadvantage: There are high chances of conflicts same variable could be used in some other part of code.


Prefix Namespacing:
Here we select a unique prefix namespace we wish to  use (in this example, myExApplication_)  and then define any methods, variables, or other objects after the  prefix as follows

Ex.
var myExApplication_propertyA = {};
var myExApplication_propertyB = {};
function myExApplication_myMethod(){ 
  //...
}

Disadvantage: We may end up having huge number of global variables thus tough manageable code.

Object Literal Notation:
Here an object contains a collection of key-value pairs with a colon separating each pair of keys and values, where keys can also represent new namespaces.

Ex.
var myExConfig = { //myExConfig is a JSON object and it contains all methods and props.

    language: "english",

    defaults: {
        enableGeolocation: true,
        enableSharing: false,
        maxPhotos: 20
    },

    theme: {
        skin: "a",
        toolbars: {
            index: "ui-navigation-toolbar",
            pages: "ui-custom-toolbar"    
        }
    }

}

Nested Namespacing:
Its an extension of Object Literal notation where an object includes another object and which in turn may include another object and so on to achieve a more granular name spacing.

Ex.
var myApp =  myApp || {};

myApp.routers = myApp.routers || {};
myApp.model = myApp.model || {};
myApp.model.special = myApp.model.special || {}


Immediately Invoked Function Expressions (IIFE)s
In IIFEs  an unnamed function is immediately invoked after it’s been defined and a namespace is passed as a parameter to contained objects.

Ex.
var namespace = namespace || {};

// here a namespace object is passed as a function 
// parameter, where we assign public methods and 
// properties to it
(function( o ){    
    o.foo = "foo";
    o.bar = function(){
        return "bar";    
    };
})( namespace );

console.log( namespace );


Namespace Injection:
This is another variation on the IIFE in which we “inject” the methods and properties for a specific namespace from within a function wrapper using this as a namespace proxy 

Ex.
var myApp = myApp || {};
myApp.utils =  {};

(function () {
  var val = 5;

  this.getValue = function () {
      return val;
  };
   
  this.setValue = function( newVal ) {
      val = newVal;
  }
      
  // also introduce a new sub-namespace
  this.tools = {};
    
}).apply( myApp.utils );  

// inject new behaviour into the tools namespace
// which we defined via the utilities module

(function () {
    this.diagnose = function(){
        return "diagnosis";   
    }
}).apply( myApp.utils.tools );