JavaScript - Namespacing

javascript

http://javascriptweblog.wordpress.com/2010/12/07/namespacing-in-javascript/ done reading, important
http://www.ethangardner.com/articles/2012/01/19/javascript-namespace-strategy-for-large-applications/ - done reading
http://jweir.github.com/namespace/
http://michaux.ca/articles/javascript-namespacing

// JavaScript - Use namespace:
var MYAPP = {};
MYAPP.stooge = {
    "first-name": "Joe",
    "last-name": "Howard"
};

By reducing your global footprint to a single name, you significantly reduce 
the chance of bad interactions with other applications, widgets, or libraries.  
Your program also becomes easier to read because it is obvious that 
MYAPP.stooge refers to a top-level structure.

What is namespacing?

To keep our code from influencing or interfering with other JavaScript code (if we are in a mash-up environment, or we use other JavaScript from third party vendor), we should use of namespaces.

What are different approaches for namespacing?

  • Using direct assignment
  • Using object literal notation
  • Using the module pattern
  • Using dynamic namespacing (namespace injection)
  • Using the this keyword as a proxy

How can we do namespacing using object literal notation approach?

Example of namespacing using object literal notation:

var myApp = {
    id: 0,
    next: function() {
        return this.id++;
    },
    reset: function() {
        this.id = 0;
    }
}

How can we do namespacing using the module pattern approach?

Example of namespacing using the module pattern:

var myApp = (function() {
    var id = 0; // private variables
    function giggle() { // private methods
    }
    return {
        x: 0,
        next: function() {
            return id++;
        },
        reset: function() {
            id = 0;
        }
    }
})();

At the heart of the module pattern is the function that get executed as soon as it is defined. This function returns an object containing public methods. In this example, id is a private variable, and x is a public variable (if we really need a public variable).

With this approach we do not have to worry about accidentally assigning namespaced function because we are using closure instead of the this keyword. Keep in mind that if we are accustomed to using the this keyword for other properties, then these properties are public properties. If we want these properties to be private properties, we will need to remove the this keyword. With JavaScript, the user can still accidentally assign a value to a property. This may not affect the public methods, but it doesn't do what the developer want it to do neither.

How can we do namespacing using the dynamic namespacing (namespace injection) approach?

Example of dynamic namespacing (also known as namespace injection):

var myMapp = {};
(function(context) {
    var id = 0;
    context.next = function() {
        return id++;
    };
    context.reset = function() {
        id = 0;
    };
})(myApp);

This example is different from the one using the module pattern. In the example of namespacing via the module pattern, we put all the public methods into an object and return that object. In this example, we do not do that. Instead, we pass the namespace as an argument to the self-invoking function under the name 'context'. The id variable is private because it is not assigned to the 'context' variable.

This (dynamic namespacing) supports all the features of the module pattern with the advantage of being able to have multiple independent instances of a module existing in separate namespaces.

I need to see an example of being able to have multiple independent instances of a module existing in separate namespaces and the advantages of doing that.

How can we do namespacing using the "this keyword as a proxy" approach?

Example of namespacing using the this keyword as a proxy:

var myApp = {};
(function() {
    var id = 0;
    this.next = function() {
        return id++;
    };
    this.reset = function () {
        id = 0;
    };
}).apply(myApp);

In this example, the namespace is injected via the this keyword (which is static within a given execution context) therefore it cannot be accidentally modified.

The 'apply' and 'call' methods provide natural separation of context and arguments therefore passing additional arguments to the module creator is very clean. The following example demonstrates this, and also shows how to run the module independently over multiple namespaces:

var subsys1 = {}, subsys2 = {};
var nextIdMod = function(startId) {
    var id = startId || 0;
    this.next = function() {
        return id++;
    };
    this.reset = function() {
        id = 0;
    };
};

nextIdMod.call(subsys1);
nextIdMod.call(subsys2, 1000);

If we want a global id generator (add our method to the global object), it's a breeze:

nextIdMod();

window.console && console.log(
    next(),
    next(),
    reset(),
    next()
);

When the function nextIdMod(), or any function, is invoked as above, and the this keyword is used inside that function, the this keyword is referring to the global object, therefore the next function is added to the global object.

By wrapping the entire library in an anonymous self-executing function, and using the this keyword as a stand-in for the namespace, we make it easy for the user to run the library in whichever context they choose (including the global context, which is just bad practice, but it is up to the users to decide):

// library code
var protoQueryMooJo = function() {
    // everything
};

// user code
var thirdParty = {};
protoQueryMooJo.apply(thisParty);

It is possible to span a single namespace across multiple .js files through namespace injection or direct assignment.

How can we do namespacing using the direct assignment approach?

One example of namespacing by assignment:

var NS = NS || {}; // "If NS is not defined, make it equal to an empty object"
NS.Utils = NS.Utils || {};
NS.Models = NS.Models || {};
NS.Views = NS.Views || {};

Another example of namespacing by assignment:

var myApp = {};
myApp.id = 0;
myApp.next = function() {
    return myApp.id++;
};
myApp.reset = function() {
    myApp.id = 0;
}

How can we make future maintenance a bit easier (in case we need to rename the namespace)?

We can make future maintenance a little easier (in case you need to rename the namespace) by using the this keyword to reference properties:

var myApp = {};
myApp.id = 0;
myApp.next = function() {
    return this.id++;
}
myApp.reset = function() {
    this.id = 0;
}

But this is a bit risky because there is nothing to stop your namespaced functions from being reassigned:

var getNextId = myAp.next;
getNextID(); // NaN

So, just do not reassign namespaced functions.

What are the advantages and disadvantages of the direct assignment approach?

The advantages are:

  1. It is easy for entry-level developer to understand

The disadvantages are:

  1. If we need to re-assign a namespaced function, we will have to use the apply or call method (extra sugar) which may make our code harder to understand / maintain.
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License