Sunday, December 2, 2007

Javascript : Simulating namespaces basic approach, part 1

we have seen in javascript scoping : things to keep in mind, that the window object was the global space englobing everything from variables to functions.
We have also seen that we could create private scoped variables and functions. Due to the 'last in, win' policy, we have also specified that we should avoid putting everything in the global space as it could lead to unexpected bugs.
We will see in this entry what are namespaces and how to simulate them in javascript.

Namespaces ?

We have seen that the window object was the global space.
We could also say that window is the name of a space, that happens to be the global one.
It doesn't really help?
Ok, in order to explain the namespace concept we are going to take an everyday life example:
You are in charge of two sports club named respectivly, Football and Basketball.
Every players receive an id and each ids are not related to each club.
If somebody came to you asking for the player 340, you will not be able to know which player it is.
if the same person asked for Football 340, you will know where to go.
Football and Basketball are therefore the names that represent a space in which you keep some related information.
the id 340 in the Football namespace doesn't represent the same player with the same id in the Basketball namespace but they do represent a person.

You could think of folders in your computer:

/usr/home/Football

and an other folder:

/usr/home/Basketball

Each of them could have a file called list.osd.
You won't have any problem as long as the files are located in different folders.
You can think of folders and their path, as namespaces too!
This is so true to life that some languages, like perl, translate packages (a way to create namespaces) into folder path!
we will see that it is a good idea and use it too in the next entry!

Namespace for what?

As you can see namespaces are a way to keep information in compartimented slot.
you can have the same id, the same variable or function names if you want:they won't run into each other as long as they are in their related namespace.
In javascript, if you don't specify anything, your variable or function will be attached to the window namespace.
If you load two libraries that define the same function name but that they don't do the same thing, it will be very hard to determine where the problem is. You might not even know that there is such a function and wonder why you don't get what you expect.

Let's see a stupid example:
// somewhere in your own set of functions
// take a pseudo array and turn it into a real javascript array
// something you could get from a DOM function
function toArray(elm) {
     var tmpArray=[];
     for(var i=0;i< elm.length;i++){
           tmpArray.push(elm[i]);
     }
     return tmpArray;
}

//somewhere in an other library, internal use:
//change a string into an array
function toArray(str) {
     return str.split();
}
Well,,, I guess you get the picture!
If you have several libraries and that you don't protect yourself from some global space pollution that may occur, you're good for hours of debugging!

Using namespaces is also a very good way to keep your code clean and organized!
Here we had Football and Basketball but in programming you could have Utilities.Strings, Utilities.Arrays,CSS.Border...
Naming and structuring your code in sub parts will allow to track easily bugs and make your life easier!
let's see how we can simulate a basic namespace.

First approach : prefix


A very easy way to simulate namespace is to simply prefix all your functions. This is a method that you can often find in language that do not support namespaces, like php for example:
__MyLibraryToArray();
Here you will prefix all your functions with '__MyLibrary'.
To some extend, this is a very basic and simple way to simulate namespace.
clash risks are decreased and one can easily see where the function comes from.
But this can start to be very cumbersome when your function names reach 30 letters length!
__MyLibraryUtilElementsToArray();
If you use this method, you are sure to type a lot and if you want to change the name..., no, you don't change your name!!

We are therefore going to see how we can make things a little bit simpler and more expandable with javascript objects!

Second Approach : functions as objects


We have seen in javascript scoping : things to keep in mind that functions allow to scope variables and other functions within them.
We could then define some private functions not accessible from outside of the function and public methods that we could call on the function name:
function Elements() {

    this.toArray = function(elm){
         var tmpArray=[];
         for(var i=0;i< elm.length;i++){
            tmpArray.push(elm[i]);
         }
         return tmpArray;
    }
}
//example of use:
var Elements = new Elements();
Elements.toArray(elm);
Let's say now that you want to put several functions that will deal with arrays, you can just rename the function to keep things coherent:
function Arrays() {

    this.toArray = function(elm){
         var tmpArray=[];
         for(var i=0;i< elm.length;i++){
            tmpArray.push(elm[i]);
         }
         return tmpArray;
    }
    this.search = function(elm,search) {
          for(var i=0;i< elm.length;i++){
              if(elm[i]===search) return i;
          }
          return false;
    }
}

//example of use:
var Arrays= new Arrays();
Arrays.toArray(elm);
Arrays.search(elm2,'hi');

but how do you do with all the code that refers to Elements.toArray??
Well, using functions to create namespaces is very powerful as you just need to create an alias that joins the old namespace with the new one:
Elements=Arrays;
And you can know create legacy code if necessary with just one line!
Something that simple prefixing will not allow you.

You could even be lazy and because you know that you are not going to use some other libraries, you want to access the function directly:
var Arrays=new Arrays();
window['search']=Arrays.search;
//now you can call it directly:
search(elm,'hi');
Here again, this shows how powerful and useful namespaces can be!

Conclusion

We have seen a very basic way of simulating namespaces in javascript thru a simple function used as a container for several related functions.
Using namespaces allow to make your code clean and organized but yet flexible as we have seen above!
This obviously allows you to protect your code or people using your code from global space pollution which can be very handy when dealing with several libraries!
Obviously, the above method is far to be the best one as we have put everything in one function.
Each time you will call the function or someone does it, all the computation within the function will be kept in memory. If you are sure that you will call the namespace just once, that can be ok but you never know!
We will see in an other entry how we can extend our namespaces functionnalities with objects!

No comments: