tags:

views:

314

answers:

3

What is the cleanest format for writing javascript objects?

Currently I write mine in the following format

if (Namespace1 == null) var Namespace1 = {};
if (Namespace1.NameSpace2 == null) Namespace1.NameSpace2 = {};

Namespace1.NameSpace2.Class1 = function(param1,param2){
     // define private instance variables and their getters and setters
     var privateParam = param1;
     this.getPrivateParam = function() {return privateParam;}
     this.publicParam1 = param2;
}

Namespace1.Namespace2.Class1.prototype = {
     publicParam1:null,
     publicFunction1:function() {/* Function body*/}
}

That format works well right now, as the YUI documentation software is able to parse it, and the comments and give back good documentation. But what it doesn't provide is a clean way to declare static global methods within the namespace. I am also wondering if there is a cleaner way to declar private variables as well.

My question is, is anyone out there have a cleaner way of defining javascript objects than this, and if so, why is your method better?

Thanks!

+4  A: 

First of all, if you don't know if Namespace1 is defined, use typeof this.Namespace1 !== "undefined", as accessing Namespace1 will throw an error if it's not defined. Also, undefined properties are undefined, not null (though undefined == null). Your check will fail if something is actually null. If you don't want to use typeof for checking if properties are undefined, use myObject.property === undefined.

Also, your second example has invalid syntax. Here is what I think you wanted to do:

Namespace1.Namespace2.Class1.prototype = {
     publicParam1    : null,
     publicFunction1 : function () {/* Function body*/}
};
Eli Grey
Yes your right, let me fix that
Zoidberg
On the namespace note, I don't actually get an error. Although I can see why your suggestion is much better practice and probably less likely to fail across different browsers. Currently that method works with IE 6+, FireFox, Sarari and Opera.
Zoidberg
A: 

Certainly rewrite the first two lines to this:

var Namespace1 = Namespace1 || {};
Namespace1.Namespace2 = Namespace1.Namespace2 || {};

The rest of the looks ok. The private variable is pretty much how everyone does it. Static methods should be assigned to the prototype, as you have done.

Do take care redefining the entire prototype for an object though, since it will prevent you from a common pattern of prototype-based inheritance. For instance:

// You inherit like this...
Sub.prototype = new Super();
obj = new Sub();

// Then you overwrite Sub.prototype when you do this:
Sub.prototype = {foo:1, bar:2}

// Instead, you should assign properties to the prototype individually:
Sub.prototype.foo = 1;
Sub.prototype.bar = 2;
Triptych
Good idea on the namespace as well. As for the prototype rewriting, it doesn't cause me too many issues as I use YUI's extend utility which allows me to do inheritance as its intended. However, without this functionality, I can see re-writing the prototype being problematic.
Zoidberg
A: 

The module pattern may help you out here:

 var Namespace1 = Namespace1 || {};
    Namespace1.Namespace2 = Namespace1.Namespace2 || {};

    Namespace1.Namespace2.Class1 = function(param1, param2) {
        // define private instance variables and their getters and setters
        var privateParam = param1;
        this.getPrivateParam = function() { return privateParam; }
        this.publicParam1 = param2;

        return {
            init: function() {
                alert('hi from Class1');
            }
        }
    } ();

You can read more about it here: http://yuiblog.com/blog/2007/06/12/module-pattern/

    Namespace1.Namespace2.Class1.init();
Olivieri
Great link, and since I am a YUI guy, definitely fits with my style, thanks a bunch!
Zoidberg