Introduction
I decided to write this tutorial because I found a clever way to create namespaces in JavaScript. In the process of creating namespaces, I found several ways of extending JavaScript to handle constructed classes, class objects, static methods and global namespace objects.
JavaScript is actually capable of almost everything C# can do, but you have to think outside of the box to create it. You must be asking yourself, "you can do all that with a function method?"... Yes! Functions are both methods and objects. In JavaScript it is fairly simple to create an object.
var obj = new Object();
or in JSON
var obj = {}
Objects are all we need to create object oriented namespaces. Below is the main code for creating namespaces. It is very small and simple, but has a lot of structuring power. Now you may ask yourself "why would I want to make my code longer on the client side?", well more and more people are moving to interactive websites that work with AJAX which has lots of complicated clientside JavaScript that needs structuring.
Below is a list of pros and cons for implementing namespaces.
Pros
- Structure
- Object Oriented Names
- Easy to Remember
- Unique Variables and Methods
- Custom Branding
- Integration with Future Web 2.0 Sites
Cons
- Longer Code
- Loading Time
- Too Complex
Well the pros outweigh the cons, plus most of the cons can be fixed too. For example, the longer code can be shorthand using aliases which I will describe later in this tutorial. Loading time can also be resolved with shorthand code; besides more people are moving to high-speed broadband and getting off the dialup connections. Another way is loading JavaScript on demand using AJAX, this will cut down on initial load times. The third issue "Too Complex!", well, have you every opened up someone's JavaScript and tried to makes sense of it right from the get go? It's very easy to get lost in code execution. So I ask you which is easier to understand? var sObj
is an object or System.Object
is an object.
Let's move on now and learn about my code and how it will help you get organized. Below is the actual namespace code for creating namespaces.
Code
var Namespace =
{
Register : function(_Name)
{
var chk = false;
var cob = "";
var spc = _Name.split(".");
for(var i = 0; i<spc.length; i++)
{
if(cob!=""){cob+=".";}
cob+=spc[i];
chk = this.Exists(cob);
if(!chk){this.Create(cob);}
}
if(chk){ throw "Namespace: " + _Name + " is already defined."; }
},
Create : function(_Src)
{
eval("window." + _Src + " = new Object();");
},
Exists : function(_Src)
{
eval("var NE = false; try{if(" + _Src + "){NE = true;}else{NE = false;}}catch(err){NE=false;}");
return NE;
}
}
Using JSON, I predefine a variable as an object with three methods.
Namespace.Register()
Namespace.Create()
Namespace.Exists()
Namespace.Register
allows you to register namespaces globally in your page. You pass a dot name string parameter to it like this:
Namespace.Register("System.Data");
This registers System.Data
for use and creates the namespaces System
and System.Data
because it is a dot notation hierarchy. The Register
method checks to see if the final dot name is already defined. If it is defined it will throw an error and if it is not, it will register it. The method Namespace.Create()
uses the eval
method to create a global object in the current window with that dot name.
Implementation
Now let's see how this code can be effective in a hello world example. In my example I have 4 files.
- namespace.js
- using.js
- helloworld.js
- example.html
Namespace.js contains the sourcecode above which we already described, so let's move to the next. Using.js is our declaration file for declaring our namespaces. The code looks like this.
Namespace.Register("System.Classes.HelloWorld");
I put this in a separate js file because you will usually have multiple definitions. We register the namespace System.Classes.HelloWorld
which registers System
, System.Classes
and System.Class.HelloWorld
. The next file helloworld.js contains our classes, methods and variables. It looks like so.
System.Classes.HelloWorld = function(){ return {
Message : "Hello World!",
Hello : function()
{
alert(this.Message);
}
};}
System.Classes.HelloDevelopers = {
Message : "Hello Developers",
Message2 : "Hello Developers Again",
Message3 : "Wassup!",
Hello : function()
{
alert(this.Message);
}
}
System.Classes.HelloMom = function()
{
var Message = "Hi";
var Message2 = "Mom!";
alert(Message + " " + Message2);
}
System.Classes.Hey = "Hey";
The first class System.Classes.HelloWorld
contains one variable Message
and one method Hello()
It is not constructed because we have wrapped it in a function()
and made it return the JSON object. This is the key to creating non constructed class objects.
The second class System.Classes.HelloDevelopers
is a preconstructed class. It contains 3 variables Message
, Message2
, Message3
and 1 method Hello()
Notice the function is removed and there is no return. It is actual ready to use and needs no construction. Another thing to point out is, we have two Hello()
named methods in this file without collision. Since they are in different namespaces they can co-exist.
The third System.Classes.HelloMom
is a static
method. It is ready to use because it is in a function wrapper with no JSON.
Fourth System.Classes.Hey
is a string variable added to one of the namespaces. It is a way of adding a var
to a page without global naming collision. As you can see with the code we do not declare any var
s to the namespaces. They are predefined as objects, variables or methods and ready to use. Now let's move on to using the code.
Our next file example.html contains the calls and construction of the classes and methods. Inside looks like this:
<html>
<head>
<script type="text/javascript" src="namespace.js"></script>
<script type="text/javascript" src="using.js"></script>
<script type="text/javascript" src="helloworld.js"></script>
</head>
<body>
<script type="text/javascript">
var HW = new System.Classes.HelloWorld();
HW.Hello();
System.Classes.HelloDevelopers.Hello();
var HW2 = System.Classes.HelloDevelopers;
HW2.Hello();
System.Classes.HelloMom();
alert(System.Classes.HelloDevelopers.Message3);
alert(System.Classes.Hey);
</script>
</body>
</html>
We insert the scripts at the top to include namespace, using, and helloworld. This needs to stay in order due to execution and creation. Next we construct an unconstructed class object and call one of its methods.
var HW = new System.Classes.HelloWorld();
HW.Hello();
As you can see we assign a var
and use new
to construct it. We then call hello world which will popup an alert with the message. This brings us to aliases. Notice now we have a var
HW
instead of System.Classes.HelloWorld()
. This is smaller and easier to manage than the full dot notation, but holds all the class methods and variables.
The second thing we use is a pre constructed class. Which we can either use with the full dot notation System.Classes.HelloDevelopers.Hello()
or alias shorthand:
var HW2 = System.Classes.HelloDevelopers;
HW2.Hello();
Both ways call the method. Notice we do not use the new
keyword to construct because we predefined it.
The next piece of code is a static
method call which is also ready to use. Just call it by name to fire the method with no construction.
System.Classes.HelloMom()
Once a class is pre constructed or constructed you can use its properties or methods. This brings us to the next line of code:
alert(System.Classes.HelloDevelopers.Message3);
This is getting the message3
string property from the System.Classes.HelloDevelopers
class and popping it up in an alert.
The last but not least piece of code is the global namespace string variable System.Classes.Hey
.
alert(System.Classes.Hey);
This is a way of using variables in the namespace scope without having them collide with other global vars.
Conclusion
Wow, OO in JavaScript, simply AMAZING! I hope you enjoyed this tutorial as much as I did creating it. Later...
Terms and Conditions For Use, Copy, Distribution, and Modification
THIS CODE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS CODE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.