PDA

View Full Version : Namespaces in Javascript



VectorX
06-02-2007, 07:36 PM
1043

Namespaces in Javascript
Description: Extending javascript to handle namespaces, classes, static methods, and global namespace variables.
Author: Adam Smith
Website: codevendor.com

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 alot 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 have 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 out weigh 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, plus 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 a object or System.Object is an object.

Lets 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.



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 so.


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 lets 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 lets move to the next. Using.js is our declaration file for declaring out 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.


// Class Example
System.Classes.HelloWorld = function(){ return {
Message : "Hello World!",
Hello : function()
{
alert(this.Message);
}
};}
//PreConstructed class with methods
System.Classes.HelloDevelopers = {
Message : "Hello Developers",
Message2 : "Hello Developers Again",
Message3 : "Wassup!",

Hello : function()
{
alert(this.Message);
}
}
//Static Method
System.Classes.HelloMom = function()
{
var Message = "Hi";
var Message2 = "Mom!";

alert(Message + " " + Message2);
}
//Global Namespace Variable
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, Message 3 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 collison. 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 collison. As you can see with the code we do not declare any vars to the namespaces. They are predefined as objects, variables or methods and ready to use. Now lets move on to using the code.

Our next file example.html contains the calls and construction of the classes and methods. Inside looks like so:


<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">
//Construct a class and call a method------------
var HW = new System.Classes.HelloWorld();
HW.Hello();
//-----------------------------------------------
//Use a PreConstructed class and call a method---
System.Classes.HelloDevelopers.Hello();
//or
var HW2 = System.Classes.HelloDevelopers;
HW2.Hello();
//-----------------------------------------------
//Static Method Call from class------------------
System.Classes.HelloMom();
//-----------------------------------------------
//Using variables from class---------------------
alert(System.Classes.HelloDevelopers.Message3);
//-----------------------------------------------
//Using variables from a namespace---------------
alert(System.Classes.Hey);
//-----------------------------------------------
</script>
</body>
</html>

We insert the scripts at 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 eaiser 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 ready to use also. 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. Which 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 final 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. Latez...

djr33
06-02-2007, 11:29 PM
(I'm actually running out the door right now, but I thought this might fit better in the tips and tricks section (bottom of the main forums page, right above the lounge). I'll take a closer look later. -- If another mod sees this and agrees, feel free to move it and delete my post.)

jscheuer1
06-03-2007, 03:58 AM
(I'm actually running out the door right now, but I thought this might fit better in the tips and tricks section (bottom of the main forums page, right above the lounge). I'll take a closer look later. -- If another mod sees this and agrees, feel free to move it and delete my post.)

I don't think VectorX has enough posts to qualify for that section, but posts may have nothing to do with it or we could wave the requirement if we so choose, perhaps.

One thing though, OO javascript isn't anything all that new and doesn't need to be so complicated. However, I have yet to see a good explanation of it that isn't complicated.

Twey
06-03-2007, 12:57 PM
I agree with jscheuer1 here, there's really nothing new or particularly interesting about the above post. It's also quite misleading to keep referring to prototype-based OO concepts with class-based OO terminology, and of course, who would want to make JS behave like C#? :)