Name space programming in Javascript

We all start javascript programming in a procedure way, the functions and variables defined in the way everything are global, global variables are evil some even claim, on the other hand when scripts getting bigger, and object programming concept is being used more and more, you are facing with a daunting task of maintaining and refactoring your existing scripts, developing new code is also getting more and more difficult. To organize the code into classes is the right way to go down, further than that how about modules or name spaces in javascript? The answer is yes.

Here is an example of procedural style of javascript where we all began with

function foo()
{
};
function bar()
{
}
foo();

There is no name space concept in javascript, all we are going to do is to organize our code in a way that looks like a namespace that we are used to in other typed programming languages like java and .net, it is actually one global object.

Basically there are two ways we can achieve this. One way is creating a literal object that

  var ns1 = {
            foo: function () { },
            bar: function () { },
            v1: 'foo'
        };

        ns1.foo();

        var v2 = ns1.v1;

 

Another way is using a top level object with constructor(not literal)

  var ns2 = new function() {

              this.foo = function () { };

              this.bar = function () { };

              this.v1 ='foo';
          };

          ns2.foo();


          var v3 = ns2.v1;

          alert(v3);

I prefer the second way than the first one, as object literal has more restrictive syntax than a function block, they are separated by commas and assigned values through ‘:’, like a json string which sometime might be diffuclt to read. the second way is also easier to wrap up your old procedure code into a name space by just including the block under a big function which is a global object served as name space (ns2)

All the functions that need to be exposed have to use ‘this’ keyword to give a clear indication of scope within the object aka namespace.

Please take a notice of new keyword of ns2, without this, it is treated like a function, you basically cannot reference a function using dot annotation, in javascript even though you can do something like this

   var ns3 = function () {

             this.foo = function () { alert('foofun') };

             this.bar = function () { };

             this.v1 = 'foo';
         };

         
      

         var ns3instance = new ns3();

         ns3instance.foo();

       //  ns3.foo(); // XXXX, it is not a function

So you will have to create an instance of ns3, it is hardly anything like the namespace we expected

There is another concept in javascript ‘self executing function’ which we do not find any equivalent in object oriented programming languages, but it is everywhere in functional programming languages like clojure or lisps

     var ns4 = (function () {

             var pub = {};

             pub.foo = function () {

                 alert('ns4');
                 alert(this);

             };



             return pub;
         } ());



         ns4.foo();
                    

Personally I would not go this way, as syntax is very hard to understand, one other thing is when you use ‘this’ keyword within self executing function, this always points to ‘window’, not the object itself, to me it does not have good modulation.

What I have shown is namespace.funcion() which is not exactly what we want for full scale object oriented programming. What we want is namespace.class references, here is the one, using foo as an object rather than function. and your modularised object oriented javascript programming starts from here.

    var ns5 = new function () {

            this.foo = function () {

                alert('ns5');
                alert(this)
            };

        };



 var o = new ns5.foo();

Update on 31 Oct 2012

To extend what I wrote before, there is some difference when you want to declare a class in namespace or declare a method in namespace, accordingly the ways of using them.


var ns = new function () {
                   
            // define a class
            this.productViewModel = function (ID) {
                var self = this;
                self.ID = ID
                alert(this);
            }
            // define a function
            this.foo = function () {
                alert('ns5');
                alert(this)
            };
        };

        $(function () {

            // use it as object
            var model = new ns.productViewModel(123);

            // use it as a static method, 
            ns.productViewModel(123);
            
            ns.foo();

        });

See above example, there is nothing different between this.productViewModel and this.foo, but actually I intend to define productViewModel as a class, and foo as a method.

When productViewModel is meant to be a class, use new key word to instantiate it. while nothing can stop you calling ns.productViewModel(123) as a method, the consequence is this context within productViewModel is different under these two scenarios, in first case, this means the productViewModel instance, but the second case, this means ns instance, as a result ID field is added to ns, while it should be contained in productViewModel.

So the lesson to take away is always use new key word to instantiate a class.

Well we now know how to use productViewModel outside of ns, what about within ns, for example in the foo function how you are going to use productViewModel? this or no this? so to further avoid the ambiguity, pass the scope to a variable, avoid to use this unless where you know what exactly this is. if this bit of code is wrapped in a namespace or highly likely to be reused, avoid using this.

Here is an example I built for knockout view model, this is passed to variable namespace imediatly


 var ns = new function () {

            var namespace = this;
            // define a class
            namespace.productModel = function (product) {
                var self = this;

                self.Id = product.Id;
                self.Name = ko.observable(product.Name);
                self.Category = ko.observable(product.Category);
                self.Price = ko.observable(product.Price);

            }

            namespace.ViewModel = function () {
                var self = this;
                self.products = ko.observableArray([]);
            }

            namespace.getProducts = function (viewModel) {
                // to populate the model
                $.ajax("@indexURL",
                 {
                     type: "get",
                     contentType: "application/json",
                     success: function (result) {
                         $.map(result,
                              function (item) {
                                  viewModel.products.push(new namespace.productModel(item))
                              });
                     }
                 });
            }

        };


        $(function () {

            var viewmodel = new ns.ViewModel();

            ns.getProducts(viewmodel);
            
            ko.applyBindings(viewmodel);

        });

In getProducts function, there is productModel to be instantiated, and under jquery.map, this or no this, you can never use productModel without using a variable.

This entry was posted on Friday, January 13th, 2012 at 12:46 am and is filed under Javascript. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

Leave a Reply

*