Matt Snider JavaScript Resource

Understanding JavaScript and Frameworks

Wednesday, July 9, 2008

Namespace Function

Today’s idea is inspired by the “YAHOO.namespace” Function of YUI. The concept is to have a method that creates your namespaces for you. In the YUI version, you pass in a String (or multiple strings) containing the new namespace(s) and they are attached to the YAHOO Object. If the namespace already exists, then you are simply returned that namespace.

Example 1: Single YUI Namespace

var myObject = YAHOO.namespace("example.mattsObject");

The example namespace is frequently used by the YUI team in their documentation. I have attached an Object (’mattsObject;) to the the example namespace (”YAHOO.example.mattsObject”). If either the “YAHOO.example” or the “YAHOO.example.mattsObject” namespaces do not exist, they will be created and the latter namespace Object will be returned, and in Example 1, assigned to ‘myObject ‘.

If you wanted to setup all your namespaces in a single call, you might do something like the following:

Example 2: Multiple YUI Namespaces

var myWidget = YAHOO.namespace("myProject.lib", "myProject.util", "myProject.widget");

This works just like example 1, except this time we setup 3 namespaces, and return the last one (”YAHOO.myProject.widget”) to set ‘myWidget’. Each namespace can be accessed directly from or you can continue to use YAHOO.namespace(myNamespace) to ensure that they always exist.

The YAHOO namespace method works great, especially, because it returns a reference to the desired namespace, but what if you do not use YUI or you want to use a different naming convention. Here is a modified version of the YAHOO namespace method that starts builds from ‘window’ instead of the ‘YAHOO’ Object.

Example 3: Modified Namespace Method

window.object_mes_namespace = function() { var a = arguments, o = window, i = 0, j = 0, tok = null, name = null; // iterate on the arguments for (i = 0; i < a.length; i = i + 1) { tok = a[i].split("."); // iterate on the object tokens for (j = 0; j < tok.length; j = j + 1) { name = tok[j]; o[name] = o[name] || {}; o = o[name]; } } return o; }

First we initialize all the variables that we will need, and create local variables to reference the Function arguments (’a') and window (’o'). We iterate through each of the arguments and split them around period, setting that Array to ‘tok’. Then iterating on each of the tokens we see if that token exists yet on ‘o’, setting it to Object when it does not, then we update ‘o’ to point to the new namespace. This keeps happening until ‘o’ is pointing to the last namespace.

Using this Function allows you to safely create your own namespaces in global without overriding any existing objects. If we took the ImagePopout Object from Simple Image Popouts we might want to change it’s implementation and attach the Object to the ‘Widget’ namespace instead of global.

Example 4: Using Namespace With ImagePopup

object_mes_namespace('Core.Widget').ImagePopout= function(bd, src, emap) { ... };

This way we ensure that both ‘Core’ and ‘Core.Widget’ objects exist, before we set ImagePopout to the popout generation Function, without having to ensure namespace existence or accidentally overriding an already existing namespace.

posted by Matt Snider at 12:08 am  

6 Comments »

  1. I’m not sure I quite understand the point of the namespace function. That said, I understand what it does. But I have a few problems with it.

    I don’t like how it returns the namespace object. This allows me to write code like object_mes_namespace( “x” ) = 3; Which to me is the equivalent of x = 3; So even if x had existed before, it doesn’t really matter, since it exists after the initialization anyway. There’s more code to create a simple assignment.

    I understand the problem that arises, if say I want to access x.attr and x is undefined. This function ensures that x exists. I also understand that this function allows you to create objects in a succinct style. I think that this function would be more useful, though, if when you come across a collision there is some sort of warning or error that occurs.

    I think this might be just an error, but shouldn’t the o object be assigned back to the window object every time you iterate through the functions arguments? Also, if try to build on top of an attribute that’s a literal and not an object, this function fails. Ex. x = 3; object_mes_namespace( “x.attr” ); Should fail.

    Comment by MillsJROSS — July 9, 2008 @ 6:30 am

  2. MillsJROSS,

    My initial thoughts were exactly that. You can modify the method by adding the following after name = tok[j]:

    if (o[name] && j === tok.length - 1) {
    throw(”Your Exception Here”);
    }

    However, after playing with the function a bit, I found myself most often using it at the beginning of a JavaScript file to ensure that the namespace I wanted to attach the new object to existed. So, if I wanted to attach a ‘Dom’ in one file and an ‘Event’ package in another file to ‘Core.Util’, then I called my function with ‘Core.Util’, in both files.

    I think sometimes you don’t want to throw an error, if the namespace exists, as with ‘Core.Util’, but other you do. For example if I called the namespace function for ‘Core.Util.Event’, as I would be overriding the event object.

    You could therefore, pass in as the last object to the namespace function a boolean, ‘throwErrorOnExistance’, which would equal:

    throwErrorOnExistance = isType(a[a.length-1], ‘boolean’) && a[a.length-1];

    and modify the error if statement to be:

    if (throwErrorOnExistance && o[name] && j === tok.length - 1) {
    throw(”Your Exception Here”);
    }

    Comment by Matt Snider — July 9, 2008 @ 8:44 am

  3. I use this functionality on my site and I did not want my namespace to be “YAHOO.SP”, i wanted it to just be “SP”. I am surprised that YUI does not just let you create a namespace in the window object as an option.

    Comment by Eric Gelinas — July 9, 2008 @ 10:03 am

  4. Hello Matt,

    I have a couple of points. First the assignment:

    object_mes_namespace(’Widget.ImagePopout’) = function(bd, src, emap) {
    //…
    };

    Doesn’t work as the left-hand side of the assignment is an expression. Did you mean:

    object_mes_namespace(’Widget’).ImagePopout = function(bd, src, emap) {
    //…
    };

    Secondly, I’ve written a somewhat long entry about namespacing. It allows for more general form of namespace declarations, and it has a complementary function ‘using’ which neatly brings a namespace into scope. Let me know what you think.

    /Karl

    Comment by Karl Krukow — July 9, 2008 @ 10:39 am

  5. Karl,

    Good catch and thanks for the link. I’ve updated the last example.

    This is why I should not write blog articles in the middle of the night ^_^.

    Comment by Matt Snider — July 9, 2008 @ 10:56 am

  6. NP, I know exactly what you mean ;-)

    Comment by Karl Krukow — July 9, 2008 @ 11:28 am

RSS feed for comments on this post. TrackBack URI

Leave a comment

Powered by WordPress