views:

138

answers:

3

I'm currently using the following pattern to create namespaces and singleton objects in Javascript:

var Namespace = function () {

    var priv = {
        privateVar1: '',
        privateVar2: '',
        privateFunction1: function () {
            //do stuff
            [...]
        },
        [...]
    };

    var pub = {
        publicVar1: '',
        publicFunction1: function () {
                //do stuff with private functions and variables
                priv.privateVar1 = priv.privateFunction1(pub.publicVar1);
            [...]
        },
        [...]
    };

    return pub;
}();

I hope you get the idea. Is there a way to create namespaces that you think is cleaner or better (explain why)?

A: 

This is good, but better to declare private variables as local variables in namespace, instead of using one object priv. Advantages: less code, packer may shrink variable names. Try to pack your code here: http://dean.edwards.name/packer/

Anatoliy
+1  A: 

Actually, it is all about semantics. If you are breaking your code apart multiple files and plan on utilizing a general namespace then doing something like this is a little bit easier:

The reason why I enjoy this method is that it is much more modular and allows for code to be broken apart into multiple files and then just as easily compressed them into one without dependency issues (unless your namespaced functions depend on one another)

The downside to this is that it can feel a bit messy at times if used incorrectly -- Which I guess can apply to anything.

In your namespace file

var Namespace = {};

In your other JavaScript files that are using the namespace

var Namespace = Namespace === undefined ? {} : Namespace;

Namespace.stuff = function () {
    var private = 'foo';
    function private_func() {
    };

    this.public = 'bar';
    this.public_func = function () {
    }
};

Some practical application would be:

GUI.js

// Some general GUI
var GUI = {
    'MAX_WIDTH': $(window).width(),
    'MAX_HEIGHT': $(window).height()
};

Toolbar.js

GUI.Toolbar = function (id) {
    var self = this;

    function init_visuals() {
        $(id).click(function () {
            self.alert_broken();
        });
    };

    function initialize() {
        init_visuals();
    };

    this.alert_broken = function () {
        alert('Broken!');
    };

    initialize();
};

Menu.js

GUI.Menu = function () {
}; GUI.Menu.prototype = new GUI.Toolbar();

Now, singletons -- That's whole another argument.

Justin Van Horne
I think your example is broken. "private" and "public" can not be used as an variable name because they are reserved: http://javascript.about.com/library/blreserved.htm. Secondly, neither "public" nor "public_func" is reachable.
Tim Büthe
He probably didn't think about it :) An you're wrong, public and public_func are reachable via Namespace.stuff.public and Namespace.stuff.public_funct.Thanks Justin, I like your method best. Thanks you too Tim, your example can be combined with other patterns and will be useful.
Kaze no Koe
Tim, yes, they are not accessible directly without declaring an instance of Namespace.stuff. They're accessible though. As for "public/private" keyword argument - It's all bullshit in my opinion. They're inheritely reserved due to the fact that all Java keywords are reserved in JavaScript. Since they are "future" reserved keywords I wouldn't worry too much.Never the less, you are right and they shouldn't be used semantically. Otherwise, it was just an example :)
Justin Van Horne
A: 

I think your example is just fine and this whole question is mostly about taste. However, I wourld write it like this:

var NAMESPACE = {

    publicVar1: '', 
    publicFunction1: (function(){

        var privateVar1 = '';
        var privateVar2 = '';
        function privateFunction1 () {
            //do stuff
            //[...]
        };

        return function(){
            //do stuff with private functions and variables
            priv.privateVar1 = priv.privateFunction1(pub.publicVar1);
        }
    })()
}

First of all, the Namespace should be all upercase, like Douglas Crockford suggests and as seen by YAHOO.

Secondly, I create NAMESPACE with its properties directly, not through an anonymous function. But I created the publicFunction1 function within an anonymous function, so I can define private functions and variables within it. That's slightly different, because the scope is even smaller then in your example. The advantage is, other functions within the same namespace can use the same variable names. The disadvantage is, well, other function don't share the same variables with that function :-)

Tim Büthe