Wednesday, January 20, 2016

C# to JavaScript: Namespacing

Namespacing is one of the most important things you can do when using js. While namespaces are built-in constructs in C#, they are not an official part of the js language. That doesn't mean that you can't or shouldn't use them, on the contrary. In this post, I'm going to show you how to create namespaces and how to add your code to the namespace to not only avoid polluting the global context, but also to avoid potential collisions with variables and functions from other js libraries.

If you are foggy on what exactly a namespace is - my definition is that it's a logical container used to provide identity and scope to related code. If a class "Languages" in C# is defined in a namespace "TDLL.Countries", the class would be accessible from code in other namespaces via TDLL.Countries.Languages or Languages if the code file is has the "using TDLL.Countries" statement outside the class definition. Now that a baseline has been established, let's take a look at some common namespaces in js.

JQuery is definitely one of those libraries that is ubiquitous. I'd say it's the most commonly used js library in the world, but then again I don't have the numbers but I bet you've used it in some capacity. The JQuery library has a namespace - 'jQuery'. Also, that namespace has an alias '$'.

Click each "Say Hello" button in the jsbin demo below to see that both jQuery and $ are the same.


jQuery Namespace on jsbin.com

JQuery has some interesting documentation on the jQuery global namespace and the $ alias here.

And this snippet from the jQuery source code on GitHub is exactly how the global namespaces are assigned:


define( [...], function( jQuery ) {
    return ( window.jQuery = window.$ = jQuery );
});

in this case "define" is a function from RequireJS which is out of scope for this post. There's a lot that goes into the "jQuery" arg that is passed to the define callback function. It is defined in the files that are omitted in the sample shown then passed into define during build time to eventually add the function to the window object (global). jQuery gives you an option to release '$' in case there is a namespace collision with other libraries - also a good practice if you are aliasing.

Another way to create a namespace is to create the namespace first, then add everything to the namespace.


window.TDLL = {};
TDLL.learnSomething = function(){ ... };

Also you could do it using object notation like this:


window.TDLL = {
    learnSomething : function(){ ... },
};


One of the challenges in defining a namespace in either of those ways is that if the namespace is already defined, you'd basically overwrite it in subsequently loaded files. To avoid that you can do the following:


window.TDLL = window.TDLL || {};
TDLL.everyDay = function(){ ... };

This neat trick evaluates the first operand of the OR (||) expression as false if it is undefined.

Another way to do this is to use jQuery to merge your new object with the existing one.


window.TDLL = $.extend(window.TDLL, {
    everyDay : function(){ ... },
});

https://api.jquery.com/jquery.extend/

jQuery Merge Demo on jsbin.com

Using your namespace is simple (once you know it has been loaded anyways).


TDLL.learnSomething();
TDLL.everyDay();

There are ways to ensure that your namespace has been loaded (by packaging all of your javascript together), but those are beyond the topic of this post and will be a topic for a future post.

No comments:

Post a Comment