HTML Markup | JavaScript | Java | Home & Links

Tutorial 17 - User-Defined Objects

Larger projects require the use of many specialized objects of a similar type. In modern languages this is normally done with user-defined objects. This tutorial shows you how to create your own specialized user-defined objects and explains the issues of constructors, prototypes and inheritance. This tutorial also describes JSON, a cross language data interchange format. Note: This page assumes familiarity with basic Object Oriented Language principles!

Object Constructors

Object constructors can be thought of as templates for making objects. As a simple example, rectangles contain several basic properties (aka variables). A simple template is:

// define a constructor with properties
function Rectangle(w,h){
  this.width=w;
  this.height=h;
  }

Note that Rectangle has its initial letter capitalized. This indicates that it is a constructor function (similar to a class in Java). The keyword this refers to the current object that called the constructor function. It identifies constructor objects and is not normally used otherwise.

Defining Constructor Methods

Methods can also be added to constructors. However they must be defined first. The names used in this definition are not important but one convention is to prepend the method name with constructor name and an underscore. It is also good practice to keep the defining methods and the constructor that uses them near each other (maybe using comments to help).

// define some methods to be included in Rectangle object
function Rectangle_area(){return this.width*this.height;}
function Rectangle_perimeter(){return 2*(this.width+this.height);}
function Rectangle_enlarge(){this.width*=2;this.height*=2;}

// define Rectangle's property display method
function Rectangle_showObj(){
  document.writeln('Width is '+this.width+'<br>');
  document.writeln('Height is '+this.height+'<br>');
  document.writeln('Area is '+this.area()+'<br>');
  document.writeln('Perimeter is '+this.perimeter()+'<br>');
  }

// define constructor with properties
function Rectangle(w,h){
  this.width=w;
  this.height=h;
  this.area=Rectangle_area; // Note: parameter brackets are not used
  this.perimeter=Rectangle_perimeter;
  this.enlarge=Rectangle_enlarge;
  this.showObj=Rectangle_showObj;
  }

// test by creating and showing an instance of the Rectangle object
myRect=new Rectangle(5,6);
myRect.showObj();
myRect.enlarge();
myRect.showObj();

This works but is very inefficient. Each instance of a new Rectangle object would contain all of the code for each method such as computing area and perimeter. The prototype based inheritance section illustrates a much better way of constructing objects.

Function Constructor Methods

Function constructor methods allow dynamic compilation of a function. An example for the area and perimeter functions used above is:

Rectangle_area=new Function("return this.width*this.height;")
Rectangle_perimeter=new Function("return 2*(this.width+this.height);")

Note that Function is capitalized (ie. an object) and uses round (ie. method) brackets.

Function literals can also be used to define a function such as:

Rectangle_area=function{return this.width*this.height;};
Rectangle_perimeter=function{return 2*(this.width+this.height);};

Note that the function is unnamed on the right hand side.

Prototype Based Inheritance

Javascript is different from the more commonly used object oriented languages such as C++ and Java in that it uses prototypes instead of classes for inheritance. Prototypes are special template objects whose properties and methods are inherited (ie pointed at, not copied to by objects created by them. This allows method code to be reused rather than copied. It also can be used to set a property to a constant value. If many objects have the same default value for a specific property but with a few exceptions, the prototype can set the default and an individual instance override the setting. A sample of a prototype approach to the Rectangle object is:

// define a couple of methods to be included in Rectangle object
function Rectangle_area(){return this.width*this.height;}
function Rectangle_perimeter(){return 2*(this.width+this.height);}
function Rectangle_enlarge(){this.width*=2;this.height*=2;}

// define Rectangle's property display method
function Rectangle_showObj(){
  document.writeln('Shape is '+this.shape+'<br>');
  document.writeln('Width is '+this.width+'<br>');
  document.writeln('Height is '+this.height+'<br>');
  document.writeln('Area is '+this.area()+'<br>');
  document.writeln('Perimeter is '+this.perimeter()+'<br>');
  }

// define constructor with properties
function Rectangle(w,h){
  this.width=w;
  this.height=h;
  this.shape="rectangle" // majority are !!
  }

// create and throw away a prototype object
new Rectangle(0,0);

// define object methods for rectangles
Rectangle.prototype.area=Rectangle_area;
Rectangle.prototype.perimeter=Rectangle_perimeter;
Rectangle.prototype.enlarge=Rectangle_enlarge;
Rectangle.prototype.showObj=Rectangle_showObj;

// test by creating and showing an instance of the Rectangle object
myRect=new Rectangle(5,6);
myRect.showObj();
myRect.enlarge();
myRect.showObj();

// and a special instance of the Rectangle object that is square
mySquare=new Rectangle(3,3);
mySquare.shape="Square"
mySquare.showObj();
mySquare.enlarge();
mySquare.showObj();

Prototypes can also be applied to any built-in object to add new methods. For example, to add the trim() method:

String.prototype.trim = function (){
   return this.replace( /^\\s*(\\S*(\\s+\\S+)*)\\s*$/, "$1");}

Subclasses

Although not often needed, subclasses (children) of user defined classes are able to be created by making their prototype objects instances of their superclass (parent). As an example we will extend a Complex object:

//constructor for subclass
function MoreComplex (real, imaginary){
  this.x=real;
  this.y=imaginary;
}
/*force the prototype to be a Complex (superclass) object
  which has been defined previously in the script */
MoreComplex.prototype=new Complex (0,0);
//now add new method or features to MoreComplex
MoreComplex.prototype.swap=function (){
  var tmp=this.x;
  this.x=this.y;
  this.y=tem;
}

Note: This makes the MoreComplex constructor property the same as its superclass. To overcome this the constructor property must be reset explicitly such as:

MoreComplex.prototype.constructor=MoreComplex;

Objects as Associative Arrays

In addition to the dot address method of identification such as object.property, object data can also be represented in array format such as object[property].

One advantage of the array representation is that the array index is a string and can thus itself be manipulated dynamically. For example to catenate all customer address data into a single string:

var addr="";
for (i=0;i <4;i++){addr+=customer["address"+i]}

The above example could have been hard coded with the dot address method but it would have been longer and less elegant. And there are times when the dynamic capability is required. For example if a client query is made for entry of a database stock item and the quantity on hand is to be obtained from the database:

var item_name=get_item_name(item); // dialog with user, dynamic answer
var quantity=database[item];
show_info(item, quantity); // display the results

And because objects can be expressed as associative arrays the powerful for-in construct can be used as illustrated in the browser explorer tool. For the above database we could quickly calculate the total inventory count without knowing the names or number of unique items in the database:

var item=""; var names=""; total=0; // variables initialized
// define a constructor with properties
function Database(){}
// construct the database
database=new Database();
// now populate the database
database.widgets=6; database.gadgets=7;
for (item in database){
   names += item+": "+database[item]+"\n";
   total += database[item];}
alert(names+"\n--------------\n"+"Total: "+total)

Javascript Object Notation

Javascript Object Notation (JSON) is a cross language data interchange format that has a much simpler syntax than XML. It is based on the constructs objects and arrays which are found in virtually all modern languages. JSON has been implemented on Java, C++, C#, Python and other languages.

More details on the syntax and use of JSON can be found at json.org



JR's HomePage | Comments [jstutorh.htm:2013 11 09]