A dissection of the ASP.NET AJAX library – Part 1: The javascript language extensions and object oriented programming

This is the first in a series of articles in which I intend to dissect the ASP.NET Ajax library. I’m relative new to this modern type of javascript programming so I decided to look into the ASP.NET Ajax library to see how certain things are done. This is a report of my voyage.

Basic concepts of the javascript language

In the next few paragraphs I will explain some of the basic concepts of the javascript language that are being used by the ASP.NET AJAX library. I will not provide a tutorial on the javascript language since you can find a lot of them on the internet, but I will provide some explanation on the more advanced language features used.

Functions in javascript

The ‘this’ variable in a function
Inside a javascript function, the ‘this’ variable is a reference to the current object which owns the function. This way, the function can alter the values of the object. If you are using the function outside the scope of an object the this variable points to the global object which is the window object in the case of javascript in browsers.

The ‘arguments’ property of a function
The arguments property consists of an array of all the arguments passed to a function. The arguments property is only available inside a function but can be used to refer to any of the function’s arguments by stating the appropriate element of the array. For example: arguments[0]; NewFunction.arguments[1] etc. (Note that the arguments property can be preceeded by the function name). So you can do stuff like this:

// Declare an instance of an object and add

//  a method

someVariable = new Object();

 

function SomethingToDo()

{

    alert(arguments.length);

 

    for(i = 0; i < arguments.length; i++)

    {

        alert(arguments[i]);

    }

};

someVariable.DoSomething = SomethingToDo;

 

// Call the method with no parameters

someVariable.DoSomething();

// Call the same method with two parameters

someVariable.DoSomething(100, “Waawwww!!”);

The arguments array is especially useful with functions that can be called with a variable number of arguments, or with more arguments than they were formally declared to accept. Inside the debug version of the Ajax library it is also used to validate the parameters passed to a function.

Objects in javascript

Extending objects
We all know javascript is a dynamic language (don’t we?), so we can do fun stuff like this:

// Declare an instance of an object

someStringVariable = new Object();

 

// Dynamically add a property

someStringVariable.theValue = “a text”;

alert(someStringVariable.theValue);

 

// Dynamically add a method

function SomethingToDo()

{

    alert(this.theValue);

};

someStringVariable.DoSomething = SomethingToDo;

someStringVariable.DoSomething();

What happens is that new properties get added to the object at runtime.
You can also use the square bracket notation to access the properties, like in the following example

alert(someStringVariable[“theValue”]);

The ‘prototype’ object in javascript
As just shown we can easily extend objects and add new properties and methods to them.
However, when I make a new object of the same type, it doesn’t have those capabilities:

someOtherVariable = new Object();

someOtherVariable.DoSomething(); // this line fails

By changing the prototype object I essentially change the definition of the type of the object and not just the one object that I added the properties or methods to

// Adding a property to the prototype

Object.prototype.theValue = “”;

 

// Adding a method to the prototype

function SomethingToDo()

{

    alert(this.theValue);

};

Object.prototype.DoSomething = SomethingToDo;

 

// For all newly created objects I can

//  use those properties and methods

someVariable = new Object();

someVariable.theValue = “A value”;

someVariable.DoSomething();

 

someOtherVariable = new Object();

someOtherVariable.theValue = “Another value”;

someOtherVariable.DoSomething();

The object literal notation

Literals
In javascript you can asign a value to a variable by using the literal notation.
If the variable is of type string you do something like:

stringVariable = “SomeString”;

If it is an integer you do

intVariable = 1;

For an array you do

myarray=[“Joe”, “Bob”, “Ken”];

Object literals
You can do the same however with an object using the object literal notation

objectVariable = {

    someVariable: 1,

    someMethod : function {

        // stuff to do …

        },

    anotherMethod : function {

        // more things to do …

        }

}

What you now have is a kind of grouping of variables and functions. But doesn’t this sound familiar? If you apply the object literal notation on an object prototype, you are adding variables and methods to the prototype of an object: you are defining something similar to a class!

Extending the language

Implementing the concept of Namespaces

In ASP.NET AJAX you can use namespaces allthough javascript doesn’t have this concept.

How do i do it?
You can define a namespace in ASP.NET AJAX by using following syntax:

Type.registerNamespace(“HFK”);

How do they do it?
If you look in the file MicrosoftAjax.debug.js, you can find following line:

Type.registerNamespace =

    function Type$registerNamespace(namespacePath) {

       // More javascript code …

    }

First things first: the Type class is a class defined by Microsoft and actually refers to the global javascript object “Function”

window.Type = Function;

window.__rootNamespaces = [];

window.__registeredTypes = {};

Because it is attached to the window object, which is the global object in browsers, you can access it from anywhere by simply using the property Type. So typing window.Type or Type is actually the same.

window.Type.registerNamespace(“HFK”);

// Following code does the same thing

Type.registerNamespace(“HFK”);

What essentially happens in this function is that the provided string is parsed in an array using dots as delimiters. This way you can define nested namespaces.

namespaceParts = namespacePath.split(‘.’);

Then the first string is used as a propertyname, remember the square brackets notation shown above, in the global window object and an empty object literal initializer is applied. Following strings are propertynames for previous namespace objects.

var rootObject = window;

for (var i = 0; i &lt; namespaceParts.length; i++) {

    var currentPart = namespaceParts[i];

    var ns = rootObject[currentPart];

    if (!ns) {

        ns = rootObject[currentPart] = {};

    }

    rootObject = ns;

}

Implementing the concept of Classes

Allthough javascript does know the concept of objects and classes through it’s prototype object, Microsoft added to this picture inheritance, interfaces and reflection. So when you define a new class, you also have to register it for Microsoft to be able to manage the other services.

How do i do it?
You can define a class in ASP.NET AJAX by using following syntax:

// Register the namespace in which the class exists

Type.registerNamespace(“HFK.Demo”);

 

// You define the constructor of the class by assigning a

//  function to the class object

HFK.Demo.Dog = function(name) {

    this._name = name;

}

 

// You define properties and methods using the object

//  literal syntax on the prototype object of your

//  newly defined class object

HFK.Demo.Dog.prototype = {

 

    getName: function() {

        return this._name;

    },

 

    Bark(): function() {

        alert(“Arff”);

    }

};

 

// register the class to the ASP.NET Ajax library

HFK.Demo.Dog.registerClass(‘HFK.Demo.Dog’);

How do they do it?
The first three sections of code should look familiar to you:

  1. Register a namespace
  2. Define the constructor for the class by assigning a function to the ‘Person’ property of the namespace
  3. Define methods for the class by initializing the prototype object

Then you must register the class to the Microsoft library so it can manage it’s internal bookkeeping.
Strangely enough, you can (and must) call this method on the Dog class itself, for which you only defined a constructor and a few other methods, but nothing like a registerClass method. What happened here?

The solution can be found in the MicrosoftAjax.debug.js file.
If you open this file you will see it starts with adding some properties and methods to the javascript native Function object, then does the same for the native Error object. Having done this it assigns the Function object to the window.Type property as described above while explaining namespaces. Then methods are added to the prototype object of the Type and thus to the prototype object of the Function object.

Now, you define the class constructor like this:

// You define the constructor of the class by assigning a

//  function to the class object

HFK.Demo.Dog = function(name) {

    this._name = name;

}

So, you assign an object of type Function to your property and by doing this your property receives all methods defined in the prototype of the type Function. And because Microsoft added those methods to the prototype of Type, which is actually a reference to the object Function, you receive all the methods added by Microsoft to the prototype of this Type object.

Mind however that you are calling a method of the class object and NOT of an object of that class !!

// register the class to the ASP.NET Ajax library

// Here you are calling a method on an object of type Function

HFK.Demo.Dog.registerClass(‘HFK.Demo.Dog’, null, null);

 

someDog = new HFK.Demo.Dog(“Fido”);

// This will NOT work because you have an object of type HFK.Demo.Dog

//  and that type does not implement a registerClass method (see the prototype)

someDog.registerClass(‘HFK.Demo.Dog’, null, null);

Implementing the concept of Inheritance

Javascript does not have the concept of inheritance as regular C# users are used to it. To mimic it you must again register your classes to the ASP.NET Ajax library

How do i do it?
First, you define two classes using the above syntax:

// Define the namespace for your classes

Type.registerNamespace(“HFK.Demo”);

 

// Define the base class

// Define a constructor for your class

HFK.Demo.Animal = function(animalType) {

    this._animalType = animalType;

}

 

// Define methods for your class

HFK.Demo.Animal.prototype = {

 

    getAnimalType: function() {

        return this._animalType;

    }

};

 

 

// Define the inheriting class

// Define it’s constructor …

HFK.Demo.Dog = function(type, name) {

    HFK.Demo.Dog.initializeBase(this,

        [type]);

 

    this._name = name;

}

 

// … and it’s methods

HFK.Demo.Dog.prototype = {

 

    getName: function() {

        return this._name;

    },

 

    Bark(): function() {

        alert(“Arff”);

    }

};

In the constructor of the inheriting class, you must call the initialization of the base class.

Next you must register the classes with the library

HFK.Demo.Animal.registerClass(‘HFK.Demo.Animal’);

HFK.Demo.Dog.registerClass(‘HFK.Demo.Dog’, HFK.Demo.Animal);

Now you can instantiate the class:

var someDog = new HFK.Demo.Dog(“Cocker Spaniel”, “Fido”);

How do they do it?
The first registration of the class is one you allready know.
The second registration does take a different form: you add to it a second parameter which is the class object from which your class derives (and not just the name of this class).

Internally, the AJAX library uses this parameter to set the __baseType property of the class you are registering. Also, a property called __basePrototypePending is set. This last property is used to resolve the inheritance at a later moment.

if (baseType) {

    this.__baseType = baseType;

    this.__basePrototypePending = true;

}

This resolving of inheritance happens the first time a method is called on the class. In our case that is the constructor call. When you call the constructor, the first thing which happens inside your constructor is the call to initializeBase which is one of those methods added to the prototype of every object by the AJAX library.

Inside the initializeBase method the method resolveInheritance() is called, also a method added by the AJAX library. Inside this method it is checked if the property __basePrototypePending is set, and if so (after calling baseType.resolveInheritance() for resolving the possible inheritance of the baseclass) each member of the baseType prototype is copied to the type for which the inheritance is resolved, providing the member does not allready exist. Now that the inheritance is resolved, the __basePrototypePending property can be destroyed.

baseType.resolveInheritance();

for (var memberName in baseType.prototype) {

    var memberValue = baseType.prototype[memberName];

    if (!this.prototype[memberName]) {

        this.prototype[memberName] = memberValue;

    }

}

delete this.__basePrototypePending;

With the inheritance being resolved and all baseType members being added, the baseType constructor can ow be applied to out object:

this.__baseType.apply(instance, baseArguments);

Implementing the concept of Interfaces

Implementing interfaces is basically the same as implementing inheritance, except that normally methods of an interface do not have any code, they are just empty methods. This last thing however is more a convention and is not enforced by the library.

How do i do it?
First, you define an interface that will be implemented by your class, and you define your class:

Type.registerNamespace(“HFK.Demo”);

 

 

HFK.Demo.IDog = function(){};

 

HFK.Demo.IDog.prototype = {

 

    getName: function(){}

};

 

HFK.Demo.IDog.registerInterface(‘HFK.Demo.IDog’);

 

 

HFK.Demo.Dog = function(name) {

    this._name = name;

}

 

HFK.Demo.Dog.prototype = {

 

    getName: function() {

        return this._name;

    },

 

    Bark(): function() {

        alert(“Arff”);

    }

};

Finally, you register the class as implementing the interface:

HFK.Demo.Dog.registerClass(‘HFK.Demo.Dog’, null, HFK.Demo.IDog);

How do they do it?
Registering the interface doesn’t do much: just the plain old adding of some properties to the class object and registering the interface with the global window object.

By registering the class as implementing the interface, first any inheritance is resolved so all methods of the class are known. Afterward the methods of the interface are, if still unavailable to the prototype of the class, copied to that prototype

this.resolveInheritance();

for (var methodName in interfaceType.prototype) {

    var method = interfaceType.prototype[methodName];

    if (!this.prototype[methodName]) {

        this.prototype[methodName] = method;

    }

}

Then, the interface is added to the list of interfaces implemented by the class:

this.__interfaces.push(interfaceType);

Implementing the concept of Enumerations

Microsoft also provides a way to make enumerations.

How do i do it?
You define an enumeration just as you would a class, except that you provide values for properties in the prototype, and not function definitions

HFK.Demo.Direction = function() {};

 

HFK.Demo.Direction.prototype = {

    Left: 0,

    Right: 1,

    Up: 2,

    Down: 3

};

Then, you must again register the enumeration with the Ajax library:

HFK.Demo.Direction.registerEnum(‘HFK.Demo.Direction’);

Now you can use the enumeration:

alert(HFK.Demo.Direction.Right);

alert(HFK.Demo.Direction.toString(HFK.Demo.Direction.Right));

alert(HFK.Demo.Direction.parse(“Right”));

By registering the enumeration with a second parameter set to “true”, you make it a flag. While ordinary enumerations can have only a single value, flags enable the combination of values by adding single values:

HFK.Demo.SomeFlag = function(){};

 

HFK.Demo.SomeFlag.prototype = {

    Value1: 1,

    Value2: 2,

    Value3: 4

};

 

HFK.Demo.SomeFlag.registerEnum(‘HFK.Demo.SomeFlag’, true);

 

alert(HFK.Demo.SomeFlag.toString(HFK.Demo.SomeFlag.Value1 + HFK.Demo.SomeFlag.Value2));

alert(HFK.Demo.SomeFlag.parse(“Value1, Value2”));

How do they do it?
If you looked at the code above I’m sure you will have noticed something strange:
Allthough you defined the enumeration values on the prototype of the class, you use them on the class object itself ! And I told you that wasn’t possible !

Well, it isn’t, however you are registering the enumeration with the ASP.NET Ajax library and inside the following happens:

for (var i in this.prototype) {

    this[i] = this.prototype[i];

}

So, all properties of the prototype of the class are transfered to the class object itself, thus enabling you to use them from the class object.

What also is done is checking you are only using integer numbers as values for the enumeration and you have not allrady used the name of the enumeration:

for (var i in this.prototype) {

    var val = this.prototype[i];

    if (!Type.__identifierRegExp.test(i))

        throw Error.invalidOperation(String.format(Sys.Res.enumInvalidValueName, i));

    if (typeof(val) !== ‘number’ || (val % 1) !== 0)

        throw Error.invalidOperation(Sys.Res.enumValueNotInteger);

    if (typeof(this[i]) !== ‘undefined’)

        throw Error.invalidOperation(String.format(Sys.Res.enumReservedName, i));

}

At the end some more properties are set (is it a flag? is it an enum?) and two methods are added to enable conversion to and from a string:

this.parse = Sys$Enum$parse;

this.__string = this.toString();

this.toString = Sys$Enum$toString;

this.__flags = flags;

this.__enum = true;

Implementing the concept of Reflection

But what is all this registering of namespaces and classes goor for? After all, if you look at how they are implemented, they all use basic javascript language features like dynamic properties, the prototype object, etc…

Reflection is what all this enables. As you have seen in the analysis of the AJAX library, there is a lot of bookkeeping that is done behind the scenes when you register a namespace or a class.

Resources:

[1] PROPERTY: Function::arguments
[2] James Mc Parlane’s Blog – The Very Useful JavaScript call() And apply() Functions For Overriding ‘this’ For A Given Function.
[3] Classifying Scopes
[4] Javascript Square Bracket Notation
[5] The prototype object of JavaScript
[6] Show love to the object literal
[7] Core JavaScript 1.5 Reference:Global Objects
[8] Extending JavaScript with ASP.NET AJAX

Updates

29 August 2007: original version
16 May 2008: corrected typos as mentioned by Nuri

Advertisements

2 thoughts on “A dissection of the ASP.NET AJAX library – Part 1: The javascript language extensions and object oriented programming

  1. Thanks for the cool article. I noticed a few of typos FYI:

    “Because it is atached”

    “the provided string get parsed”

    The line “return this._firstName” should be “return this._name”

    Cheers,
    Nuri

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s