Namespaces in JavaScript – Global Variable – A complete understanding

Namespaces

In most programming languages we know the concept of namespaces (or packages). Namespaces allow us to group code and help us to avoid name-collisions.

In c# for example you have this declaration

1
2
3
4
5
6
namespace MyNameSpace
{
    public class MyClass
    {
    }
}

If you want to use MyClass, you need to do explicitly say in which namespace it lives:

1
MyNameSpace.MyClass obj;

Unfortunately, the concept of namespaces does not exist in JavaScript. To add insult to injury, everything you create in JavaScript is by default global. Now obviously, this is a recipe for disaster, especially since in any modern application you’ll probably end upll using third-party components. How do you avoid these collisions then?

Let’s first look at an anti-pattern, which is declaring all your functions and variables globally:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function calculateVat(prod) {
    return prod.price * 1.21;
}
var product = function (price) {
    this.price = price;
    this.getPrice = function(){
                       return this.price;
        };
    };
function doCalculations() {
    var p = new product(100);
    alert(calculateVat(p.getPrice()));
}

This is a simple snippet, but there are already 3 global items: CalculateVat, product and doCalculations. This could get us in trouble if we start using third-party libraries. What would happen if they use the same names? Well, if they are includedafter our script, they will overwrite our variables and function. Bad! If they’re included before our script, we’re overwriting their variables, which is also bad, since we’ll probably break the library.

How to create a namespace in JavaScript

To solve this problem you can create a single global object for your app and make all functions and variables properties of that global object:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var MYAPPLICATION = {
    calculateVat: function (base) {
        return base * 1.21;
    },
    product: function (price) {
        this.price = price;
        this.getPrice = function(){
                          return this.price;
                       };
    },
    doCalculations: function () {
        var p = new MYAPPLICATION.product(100);
        alert(this.calculateVat(p.getPrice()));
    }
}

Now we only have one global variable (MYAPPLICATION). Although this is not really a namespace, it can be used as one, since you have to go through the MYAPPLICATION object in order to get to your application code:

1
2
var p = new MYAPPLICATION.product(150);
alert(p.getPrice());

Nested namespaces

In most languages you can declare a namespace inside a namespace. This allows for even better modularization. We can just apply the pattern again and define an object inside the outer object:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var MYAPPLICATION = {
    MODEL: {
        product: function (price) {
                     this.price = price;
                    this.getPrice = function(){
                         return this.price;
                     };
                 }
    },
    LOGIC: {
        calculateVat: function (base) {
            return base * 1.21;
        },
        doCalculations: function () {
            var p = new MYAPPLICATION.MODEL.product(100);
            alert(this.calculateVat(p.getPrice()));
        }
    }
}

This pattern is fairly simple and is a good way to avoid naming collisions with other libraries (or your own code for that matter).

Safely creating namespaces

Since we still have one global object, there’s still a possibility that we are overwriting another global object with the same name. Therefore, we need to build in some safety:

1
2
3
4
5
6
7
8
9
10
// not safe, if there's another object with this name we will overwrite it
var MYAPPLICATION = {};
// We need to do a check before we create the namespace
if (typeof MYAPPLICATION === "undefined") {
    var MYAPPLICATION = {};
}
// or a shorter version
var MAYAPPLICATION = MYAPPLICATION || {};

As you can see in this example, if we want to safely create namespaces it can be quite cumbersome and require a bit of boilerplate code. Wouldn’t it be nice if we could avoid all of this?

Creating a multi-purpose Namespace function

What we’d like to do is simply call a function that creates a namespace safely and then lets us define function and variables in that namespace. Here’s where JavaScript’s dynamic nature really shines. Let’s start with an example of what we want to achieve:

1
2
3
4
5
6
7
8
9
10
var MAYAPPLICATION = MYAPPLICATION || {};
var ns = MYAPPLICATION.createNS("MYAPPLICATION.MODEL.PRODUCTS");
ns.product = function(price){
   this.price = price;
   this.getPrice = function(){
    return this.price;
   }
};

We still need to check our main namespace (you have to start somewhere), but it will allow us to create a hierarchy of namespaces with a single line and have it all figured out.

So how can we do that? Let’s take a look at the implementation of createNS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
MYAPPLICATION.createNS = function (namespace) {
    var nsparts = namespace.split(".");
    var parent = MYAPPLICATION;
    // we want to be able to include or exclude the root namespace so we strip
    // it if it's in the namespace
    if (nsparts[0] === "MYAPPLICATION") {
        nsparts = nsparts.slice(1);
    }
    // loop through the parts and create a nested namespace if necessary
    for (var i = 0; i < nsparts.length; i++) {
        var partname = nsparts[i];
        // check if the current parent already has the namespace declared
        // if it isn't, then create it
        if (typeof parent[partname] === "undefined") {
            parent[partname] = {};
        }
        // get a reference to the deepest element in the hierarchy so far
        parent = parent[partname];
    }
    // the parent is now constructed with empty namespaces and can be used.
    // we return the outermost namespace
    return parent;
};

This function splits the string you pass it and creates a nested namespace for each part. This means that this code:

1
MYAPPLICATION.createNS("MYAPPLICATION.MODEL.PRODUCTS");

is essentially the same as declaring the following (but with the advantage of checking whether we’re not overriding any existing namespace):

1
2
3
4
5
6
var MYAPPLICATION = {
    MODEL: {
        PRODUCTS: {
        }
    }
}

Aliasing namespaces

When your namespace hierarchy becomes deeper and deeper you will notice that it becomes cumbersome since you always have to type the complete reference to a function or a variable. This can easily be solved by aliasing a namespace (similar to the using statement in C# and Imports in JAVA and VB). Let’s take a look at an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
MYAPPLICATION.createNS("MYAPPLICATION.MODEL.PRODUCTS");
MYAPPLICATION.createNS("MYAPPLICATION.LOGIC.BUSINESS");
MYAPPLICATION.MODEL.PRODUCTS.product = function(price){                                          
    this.price = price;   
    this.isVatApplicable = true;
    this.getPrice = function(){                                              
        return this.price;                                           
    }                                      
};
MYAPPLICATION.MODEL.PRODUCTS.currentvatrate = 1.21;
MYAPPLICATION.LOGIC.BUSINESS.getSelectedProductTotal = function () {
    var p = new MYAPPLICATION.MODEL.PRODUCTS.product(100);
    if(p.isVatApplicable){
        return p.getPrice() * MYAPPLICATION.MODEL.PRODUCTS.currentvatrate;
    }
    else {
        return p.getPrice();
    }
}

This simple snippet declares two namespaces and then adds an object to the first and a function to the second. The function uses the object in the other namespace. As you can see, this simple method which just uses one function and a couple of variables is very cumbersome to write because of all the references.

A shortcut would be easier. We can achieve this by simply aliasing the namespace in a local variable:

1
2
3
4
5
6
7
8
9
10
MYAPPLICATION.LOGIC.BUSINESS.getSelectedProductTotal = function () {
    var model = MYAPPLICATION.MODEL.PRODUCTS;
    var p = new model.product(150);
    if (p.isVatApplicable) {
        return p.getPrice() * model.currentvatrate;
    }
    else {
        return p.getPrice();
    }
}

Apart from saving you typing work and decreasing your file size, this pattern has one more advantage that I think is even more important. Since you are declaring your namespace at the top of each function, you are explicitly clarifying in your code on what module it depends. That, in my opinion, is invaluable and will help you understand written code a lot better.

Disadvantages

Although this pattern is easy to use and perfectly valid for many tasks and scenarios there is one big disadvantage:

The one global instance is vulnerable. This means that anyone could access its internals. For example, the product has a property price and a method getPrice(). However, nothing prevents us from directly accessing the price property. We don’t want this, we want to expose only the method so we can control the access to our private variable.
To solve these problems we need to take a look at how can create modules that encapsulate certain data and behavior.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s