Namespaces in Javascsript

I am a recent convert from the good land of OOP languages (class oriented languages to be technically correct), to the bizarre land of Javascript (truly object oriented). Doing Javascript for fun is one thing but doing it at a large scale professionally requires certain practices that have been built over the years in enterprise world. One such practice is organizing your classess (function objects), into logical partitions or rather namespaces.
Like quite a few things that a regular C#/Java guy would find amiss in Javascript, namespaces are one such thing. As I work more with Javascript, one thing that hits is there are not many bits and pieces to learn really. In C#/Java you got to learn many aspects of the language itself, but in Javascript it just functions and you got to build everything from it. Now lets consider how we might create a namespace to organize our function objects into each of them correctly. Say we need to generate namespaces like,
  • Hogwarts,
  • Hogwarts.Griffindor
  • Hogworts.Griffindor.Muggles
  • Hogworts.Griffindor.Wizards
Below code snippet just does that,
 var Hogwarts = Hogwarts || {};
Hogwarts.Griffindors = Hogwarts.Griffindors || {};
Hogwarts.Griffindors.Muggles = Hogwarts.Griffindors.Muggles || {};
Hogwarts.Griffindors.Wizards = Hogwarts.Griffindors.Wizards || {};
Hogwarts.Griffindors.Wizards.Harry = function(){
    this.name = 'Harry Potter';
};
Hogwarts.Griffindors.Wizards.Ron = function(){
    this.name = 'Ronald Weasley';
};
Hogwarts.Griffindors.Muggles.Hermione = function(){
    this.name = 'Hermione Granger';
};
This creates a Hogwarts object at window level and organizes all other objects under it. This works just fine but a bit verbose and repetitive I bet. A cleaner way could be to generate these objects on the fly as long as you pass the namespace string correctly. Here is a method that generates Harry, Ron and Hermoine in their respective namespaces,
 var namespace = function (ns) {
    var parts = ns.split('.');
    if (!parts || parts.length === 0) {
        return;
    }
    window[parts[0]] = window[parts[0]] || {};
    var current = window[parts[0]];
    var startIndex = 1;
    for (var i = startIndex; i < parts.length; i++) {
        var part = parts[i];
        if (!current[part]) {
            current[part] = {};
        }
        current = current[part];
    }
    return current;
};
And now we just create the objects we want.
 var Wizards = namespace('Hogwarts.Griffindors.Wizards');
Wizards.Harry = function(){
    this.name = 'Harry Potter';
};
Wizards.Ron = function(){
    this.name = 'Ronald Weasley';
};
var Muggles = namespace('Hogwarts.Griffindors.Muggles');
Muggles.Hermione = function(){
    this.name = 'Hermione Granger';
};
If you think about how .NET or Java deserialization works, as long as the assembly being loaded matches the type we are deserializing, we get an instance of the type. We do not have to do anything speacial. But of course in Javascript, there is no type! What if we want to create an object on the fly by just knowing its “full type name” like Hogwarts.Griffindors.Wizards.Harry. It need not be very difficult since we already have a method that can generate namespaces right. We can have a separate method that is responsible for just this,
 var create = function(fullNameSpace, args){

    var parts = fullNameSpace.split('.');
    if(!parts || parts.length === 0){
        return;
    }
    window[parts[0]] = window[parts[0]] || {};
    var current = window[parts[0]];
    var startIndex = 1;
    for(var i=startIndex;i < parts.length; i++){
        var part = parts[i];
        if(!current[part]){
            return;
        }
        current = current[part];
    }
    return new current(args);

};
And now we happily create our characters by passing their “full type name”,
 var harryInstance = create('Hogwarts.Griffindors.Wizards.Harry');
console.log(harryInstance.name);
var ronInstance = create('Hogwarts.Griffindors.Wizards.Ron');
console.log(ronInstance.name);
var hermioneInstance = create('Hogwarts.Griffindors.Muggles.Hermione');
console.log(hermioneInstance.name);
Javascript deserialization in the works baby!!!
Happy Typing

Abhang Rane


1 comment :

Reader's Comments