Search code examples
javascriptclassnamespacesfunction-prototypes

Javascript namespace declaration with function-prototype


I know, this is often discussed. But after searching around like someone out of the 19th century, I need some advice. I have no problem by declaring a "namespace", but when it comes to a prototype.foo function, I stuck. I found a way, but I don't like it:

Namespace = {}
Namespace.obj = function() {
    this.foo="bar";
}
Namespace.obj.prototype.start = function() {
    this.foo="fubar";
}

blah = new Namespace.obj();
blah.start();

Now, since I'm a little neurotic in case of scripting, I would like to have something like this:

Namespace = {
    obj: function() {
        this.foo="bar";
    },
    obj.prototype.start: function(tabinst) {
        this.foo="fubar";
    }
}
...

But then it throws an error: "Uncaught SyntaxError: Unexpected token ."

I know, this is cosmetic, but I think that there has to be a better method of declaring a "namespace" containing a class and prototype functions.


Solution

  • The way I would do it is using the "Module pattern".
    You basically encapsulate all your "Module" logic in a self executing function that would return an object having your classes, functions, variables etc... Think of the return value as exposing your Module API.

    Namespace = (function () {
        /** Class obj **/
        var obj = function () {
            this.foo = 'bar';
        };
        obj.prototype = {
            start: function () {
                this.foo = 'fubar';
            }
        };
    
        /** Class obj2 **/  
        var obj2 = function () {
            this.bar = 'foo'
        };
        obj2.prototype = {
            start: function () {
                this.bar = 'barfoo';
            },
            end: function () {
                this.bar = '';
            }
        };
        return {
            obj : obj,
            obj2: obj2
        };
    })();
    
    var o = new Namespace.obj()
    o.start()
    

    In order to further encapsulate the "obj" class methods and constructor we could do the following:

    /** Class obj **/
    var obj = (function () {
        /** class Constructor **/
        var obj = function () {
            this.foo = 'bar';
        };
        /** class methods **/
        obj.prototype = {
            start: function () {
                this.foo = 'fubar';
            }
        };
        return obj;
    })();
    

    There is also an important feature that comes for free using this pattern, which is "Private variables", consider the following:

    /** Class Foo **/
    var Foo = (function () {
        // Private variables
        var private_number = 200
        /** class Constructor **/
        var Foo = function () {
            this.bar = 0;
        };
        /** class methods **/
        Foo.prototype = {
            add: function () {
                this.bar += private_number;
            }
        };
        return Foo;
    })();
    
    foo = new Foo();
    alert(foo.bar); // 0
    foo.add(); 
    alert(foo.bar);// 200
    alert(foo.private_number) //undefined