How to set up JavaScript namespace and classes properly?
Solution 1:
Do neither of those things.
Make a javascript "class":
var MyClass = function () {
var privateVar; //private
var privateFn = function(){}; //private
this.someProperty = 5; //public
this.anotherProperty = false; //public
this.someFunction = function () { //public
//do something
};
};
MyNamespace.MyClass = new MyClass();
One with static vars:
var MyClass = (function(){
var static_var; //static private var
var MyClass = function () {
var privateVar; //private
var privateFn = function(){}; //private
this.someProperty = 5; //public
this.anotherProperty = false; //public
this.someFunction = function () { //public
//do something
};
};
return MyClass;
})();
MyNamespace.MyClass = new MyClass();
With a "constructor" (all of the examples have a "constructor", this one just has parameters to work with):
var MyClass = function (a, b c) {
//DO SOMETHING WITH a, b, c <--
var privateVar; //private
var privateFn = function(){}; //private
this.someProperty = 5; //public
this.anotherProperty = false; //public
this.someFunction = function () { //public
//do something
};
};
MyNamespace.MyClass = new MyClass(1, 3, 4);
With all of the above you can do:
MyNamespace.MyClass.someFunction();
But you cannot do (from the outside):
MyNamespace.MyClass.privateFn(); //ERROR!
Solution 2:
The first example is simply an Object literal - it cannot be instantiated and doesn't have private members. The second example has some incorrect syntax (var someProperty: 5
should be var someProperty = 5
) but is using a closure to encapsulate internal private state within a self-invoking anonymous function.
The second approach looks better for encapsulating private members, but could be made more "Object-oriented" by making it an instantiable class:
MyNamespace.MyClass = function() { ... };
MyNamespace.MyClass.prototype.someProperty = 'foo';
Then you can instantiate it with the 'new' keyword:
var aClass = new MyNamespace.MyClass();
aClass.init(...);
Solution 3:
I use the following syntax for the instantiable classes with namespace
var MYNamespace = MYNamespace|| {};
MYNamespace.MyFirstClass = function (val) {
this.value = val;
this.getValue = function(){
return this.value;
};
}
var myFirstInstance = new MYNamespace.MyFirstClass(46);
alert(myFirstInstance.getValue());
jsfiddle: http://jsfiddle.net/rpaul/4dngxwb3/1/
Solution 4:
Why you should never use
return { methodName : methodDelegate}
like in second example:
MyNamespace.MyClass = (function () {
var someProperty = 5;
var init = function () {
//do something
};
return {
someProperty: someProperty
someFunction: someFunction
};
}());
MyNamespace.MyClass.init();
When you use namespace you have to think about it as about declaration, not the instance.
MyNamespace = {};
MyNamespace.sub = {};
MyNamespace.anotherSub = {};
MyNamespace.sub.MyClass = (function () {
var static_var; //static private var
var MyClass2 = function () {
var privateVar; //private
var privateFn = function () { }; //private
this.someProperty = 5; //public
this.anotherProperty = false; //public
this.someFunction = function () { //public
//do something
};
};
return MyClass2;
})();
debugger;
var c1 = new MyNamespace.sub.MyClass();
c1.someProperty = 1; // creates 5->1.
var c2 = new MyNamespace.sub.MyClass();
c2.someProperty = 2; // creates 5->2. c1 is still 1
debugger;
var myClass = function () {
var someProperty = 5;
var anotherProperty = false;
var init = function () {
//do something
};
var someFunction = function () {
//do something
};
return {
someProperty: someProperty,
anotherProperty: anotherProperty,
init: init,
someFunction: someFunction
};
};
MyNamespace.MyClass = myClass();
var c2 = MyNamespace.MyClass;
// how are planning to create one more object, while it's a reference? copy //the whole one?
c2.someProperty = 2; // changes 5 -> 2
var c3 = MyNamespace.MyClass.init(); // create 2 instead of 5
c3.someProperty = 3; // changes c3 and c3 from 2 to 3.
console.log(c2.someProperty + c3.someProperty);
And no metter how much Module anti-patter was popular. Declaration gives you an ability to use the same code with different instances in an expected way for other developers . The quality of code and simplicity of its reading increases. The goal of any developer is to write a simple code to be read, not a shorter or D.R.Y. - but simple to be read and be understanded by another developer. That decreases the number of bugs first. (c) S. McConnell
Solution 5:
How to combine namespace and class declaration:
var ns = { // your namespace
my_value: 1, // a value inside the namespace to avoid polluting
MyClass: function() { // a class inside the namespace
this.class_property: 12,
this.class_method: function() {
console.log("My property: " + this.class_property);
}
},
myFunction: function() { // a function inside a namespace
console.log("I can access namepsace value if you don't use 'new': " + this.my_value);
}
};
Accessing your value:
console.log(ns.my_value);
Now, for the Class and Function: If you use new
, the word this
inside the function will point to it's constructor. If you don't use new
, this
will point to the namespace. So,
Using a Class:
var obj = new ns.MyClass();
Using the Function:
ns.myFunction();
If you construct the object without new
, this
will point to the namespace, so the namespace will be "destroyed" because MyClass.class_property
and MyClass.class_method
will be added to it.