provided by: 
Originally published at Internet.com
Series Description
The AJAX from Scratch series of articles describes fundamental techniques needed to develop AJAX Rich Internet Applications in JavaScript from scratch. Each article focuses on a particular (usually little-covered) aspect of developing browser-side functionality without the use of commercial or server-based frameworks. The techniques described are illustrated in Gravey, a small, but real-world, JavaScript framework for AJAX and RIAs.
Abstract
With the increasingly popular AJAX and RIA paradigms, the impetus to build complicated dynamic user interfaces is driving developers to use the same design patterns (e.g. Model-View-Controller) formerly tied to "fat" GUI clients. All of these design patterns expect the consistency of class-based objects as provided in languages like C++ and Java. However, since JavaScript does not use classes, Rich Internet Applications must emulate their functionality. This article describes one such emulation technique and demonstrates why many commonly used techniques fall short.
In order to develop non-trivial logic in JavaScript, and especially when using standard design patterns, a platform is needed that provides for programming with classes. An implementation of such a platform is presented that is based on the techniques used in the Gravey framework. Presented is a very small set of JavaScript code and programming conventions that together emulate classical classes of the sort familiar to C++ and, in particular, Java programmers.
For those object-oriented developers whose experience with JavaScript has been shallow or not particularly object-oriented (e.g. the author a few years ago), it may not be obvious why such a platform is needed. It is only when understanding how JavaScript actually works, and why simplistic approaches to JavaScript "classes" fail, that it becomes apparent why the particulars of the presented platform are needed.
JavaScript doesn't already have Classes?!
Or, Prototype-based vs Class-based, Dynamic vs Static, Weakly-typed vs Strongly-typed
Just as a person, born and confined to an entirely blue room, has a hard time conceiving of green, the typical OO programmer has a hard time imagining objects and inheritance without classes. JavaScript is a language with objects and inheritance but no classes. For casual JavaScript programmers, this fact is often not even known because (a) JavaScript has syntax that is deceptively similar to Java, even though something completely different is going on semantically
(b) Many web development texts talk as if JavaScript has merely a slightly different syntax from Java, rather than describing how they are fundamentally different categories of languages.
JavaScript is generally a prototype-based language; where each object is not constructed from a predefined template of attributes and methods (i.e. a class), but is effectively just a dynamic associative array of attribute names and values. In other words, JavaScript allows each object's attributes to be dynamically created and deleted at runtime. It also (not being strongly-typed) allows the same attribute (or any variable for that matter) to be assigned values of different data types over time. And finally, an attribute value can be a Function object which can be invoked in a manner similar to a method. JavaScript has syntactic sugar; to make creating object instances, accessing their attributes, and invoking their "methods", look like Java syntax.
Regarding subclasses, Java's classical inheritance; defines one class as a subclass of another thus inheriting its methods and attributes. When a class instance (i.e. an object) is created, that object has all the attributes and methods of the class' entire inheritance hierarchy. With JavaScript's prototype inheritance, an object may point to another object as its "prototype". When reading an object attribute, if that attribute is not found, the object's prototype will be searched. Since that prototype object may, in turn, point to another prototype of its own, an entire inheritance chain may be built (ala a class hierarchy).
A big difference, however, is that prototypes, being simple objects, may be changed at runtime and hence dynamically change what is being inherited. On the other hand, if multiple prototype objects of the same "class" are created, changes to one prototype object will not be seen by those pointing to different prototype objects. Further more, when assigning a value to an inherited attribute, the prototype object is not changed. Instead, a new attribute with the same name is created on the top-level object, SO, implementing "class" (aka static) attributes via simple prototype objects doesn't really work.
Note that I described JavaScript as "generally prototype-based". This is because it has other features that look a lot like classes! JavaScript allows functions to be used as "class" constructors; and recognizes their names via the instanceof operator. JavaScript also has several predefined "classes" (e.g. Date, String, Function, etc.).
The GrvObject Approach
With the presented technique, it is a simple matter (as shown in Listing 1) to declare a class along with its superclass, constructor, and methods, as well as, to use "super".
Listing 1. Simple example using the GrvObject technique 1 Class(A); 2 function A() 3 { 4 this.konstructor = function( arg1 ){ this.bar = arg1; } 5 this.aMethod = function( ... ){ ... } 6 this.anotherOne = function( ... ){ ... } 7 } 8 9 Class(B).Extends(A); 10 function B() 11 { 12 this.konstructor = function( arg1, arg2, optionalArg3 ) 13 { 14 this.souper( arg2 ); //ie. invoke "A.konstructor" 15 this.foo = arg1; 16 } 17 18 this.aMethod = function(...){ this.souper(42); ... } 19 this.yetMore = function(...){ ... } 20 } 21 22 var x = new B(3,4,5);
Normal looking JavaScript "constructor" functions are defined in lines 2-7 and 10-20 except that any logic other than defining methods is contained in the special "konstructor" method.
The Platform Implementation
While the complete documented version of the platform. is contained in a few JavaScript include files, the compact, standalone code in Listing 3 implements the basic technique. Lines 12-18 implement the "super" capability. Lines 27-31 replace the original class function with a wrapper function that, in turn, uses the original class as its prototype. Instances of the wrapper class will hold all the instance variables and only the singleton prototype objects contain method definitions.
Listing 3. The GrvObject technique's basic implementation (grvObject.js) 1 Class(GrvObject); //special root class 2 function GrvObject(){ 3 this.souper = function() { 4 var superMethod = this.souper.caller.souper; 5 return (superMethod) ? superMethod.apply( this, arguments ) : null; 6 } 7 } 8 9 function grvExtends( superClass ){ //link super and sub classes 10 this.baseClass.prototype = (this==GrvObject) ? null : superClass.prototype; 11 this.prototype = new this.baseClass(); 12 if (this.baseClass.prototype) 13 for (var x in this.prototype) { // iterate over all properties 14 var m = this .prototype[x]; // the method 15 var s = this.baseClass.prototype[x]; // its super 16 if (s && (s!=m) && (m instanceof Function) && (s instanceof Function)) 17 m.souper = s; 18 } 19 } 20 21 function grvFuncName(f){ //extract name from function source 22 var s = f.toString().match(/function\s*(\S*)\s*\(/)[1]; 23 return s ? s : "anonymous"; 24 } 25 26 function Class( theClass ){ 27 var originalClass = theClass; 28 self[ grvFuncName(theClass) ] = theClass = function(){ 29 arguments.callee.prototype.konstructor.apply( this, arguments ); 30 } 31 theClass.baseClass = originalClass; 32 theClass.Extends = grvExtends;//so we can call Extends as a method 33 theClass.Extends(GrvObject);//required here even if overridden later 34 return theClass; 35 }
The utility function grvFuncName (lines 21-24) takes a function object and returns the function name (made possible because, in JavaScript, the function object contains the function source code).
Conclusion
With the presented compact implementation. JavaScript developers can take advantage of most of the features of Java classes, thus enabling the use of robust design patterns needed for AJAX and RIA applications. Use of this technique does not preclude mixing in other techniques or legacy code thus allowing the technique to be added to existing code.
Examples
The source code in this article is available for viewing or download at Polyglotinc.com or here at Developer.com.
About the Author
As principal consultant of PolyGlot, Inc., Bruce Wallace has provided consulting and custom computer software development services around the world. Projects have been completed in Sydney Australia, Perth West Australia, "Silicon Valley", "Route 128" MA, Austin TX, Atlanta GA, and Charlotte NC.
Copyright
© Copyright, 2006-2007, PolyGlot, Inc.
Author: Bruce Wallace
Read article at Internet.com site