ECMA-262 Core: User Defined Class in JavaScript





Navigation Aids -- This Page        Navigation Aids -- This Topic        Navigation Aids -- This Site








Introduction And Review

User Defined Class: the programmer can build custom classes in his JS program. The custom class is a set of properties and methods that have been aggregated together into a single unit. This unit (class) may contain values of primitive types or other classes such as functions and arrays. Together, the members of the class work to accomplish a common goal that is intrinsic to that class.

In formal OOD terms, we create a custom type or class. The user defined class type can then be used to instantiate objects of that class type. Object instances will inherit the properties and methods of the custom class type.

As with Native classes, our custom class type can have constructor functions, a prototype object, class properties, class methods, instance properties and instance methods.

We have defined the OOD/OOP terms together on a separate page. Terms are explained from a Java perspective and then from a JavaScript perspective. To view the OOD/OOP terms together, take this link.





Illustration Summary

We will present the topic of User Defined Class via an illustration. Our custom class will be a Clock.

To build and utilize our custom class of type Clock, we will proceed in a logical order. Each step will be illustrated with code examples and an explanation. A outline of each step follows:

  1. Build the Constructor
  2. Build an Instance of the class type Clock
  3. Establish the Prototype Object for the class type Clock
  4. Define a Constant for the Prototype Object of class type Clock
  5. Define a Method for the Prototype Object of class type Clock
  6. Call the new Method from our Clock Object
  7. Instance Methods
  8. Class Methods
  9. Instance Properties
  10. Class Properties

To this point we have illustrated the basics of implementing a user define class. What follows are some additional topics that expand on the above or provide variations to the above.

  1. Multiple Constructors
  2. Display the Property Names of an Object
  3. Delete a Property
  4. Methods Assigned to a Constructor (a no no)
  5. Function Literal Example




A Step By Step Approach


1. Build the Constructor


// Note 01 function Clock(hours, minutes, seconds)// Note 02 // Note 03 { this.hr = hours; this.min = minutes; this.sec = seconds; }
Note 01:
The constructor defines our class.
Note 02:
This function statement acts as the constructor for our new class type Clock. The name of the function (and class) is "Clock". This function statement's header defines three formal parameters (arguments); hours, minutes, and seconds. When this constructor is invoked, the invoking statement should pass three actual arguments to the class type Clock constructor.
Note 03:
The body of the function statement defines three instance properties (hr, min and sec). The this keyword is a reference to the object being instantiated. Each object instance of class type Clock that is instantiated via the constructor will receive the properties (hr, min and sec). Furthermore, these three instance properties will be assigned the values that were passed as actual parameters when the constructor was invoked.

2. Build an Instance of the Class Type Clock


var myClock = new Clock( 9, 56, 22);// Note 01: // Note 02: alert(myClock.hr);// returns 9 alert(myClock.min);// returns 56 alert(myClock.sec);// returns 22
Note 01:
The class of type Clock is invoked with the new operator. The new operator along with the constructor function will initialize a new instance of the class type Clock. Furthermore, the pointer to the new object instance is assigned to the variable myClock. Here, the variable myClock acts as a reference type variable.
Note 02:
The dot operator is used to access a property of myClock.

3. Establish the Prototype Object for the Class Type Clock

This is a do nothing step. We as programmers do not create the prototype object. In JavaScript, every function is automatically given a prototype object (just in case the function is used as a constructor).

Why do we care about the prototype object? It is the prototype object that supports inheritance in JavaScript. In future steps of our illustration, we will be adding properties and methods to the prototype object of the class type Clock.

As a sidebar; to be safe, you may want to add the following line of code. With JavaScript 1.1 and earlier versions, the prototype object was not created until the constructor function is invoked.

new Clock(0, 0, 0 ); // forces the prototype object to be created // the dummy object is created and discarded

4. Define a Constant for the Prototype Object of class type Clock


// Note 01 Clock.prototype.maxhr = 24; Clock.prototype.maxmin = 60;// Note 02 Clock.prototype.maxsec = 60; // Note 03
Note 01:
Here we are defining three constants; these properties will be shared by all objects of the Clock class. Be aware that maxhr, maxmin and maxsec are not real constants in the traditional sense. A true constant can not be reassigned or altered. However, because these properties are defined with the prototype object, the programmer could but should never change them (quality of a constant) or else all objects instances of the Clock class type will also be changed.
Note 02:
60 minutes in an hour
Note 03:
As a side note, the myClock object instantiated in step 2 will inherit these new properties even when the constant's definition occurs after myClock was instantiated.

5. Define a Method for the Prototype Object of class type Clock


// first declare the function // this function will set the time of a Clock object function setTime_Clock( hours, minutes, seconds) { if ( hours >= 0 && hours < 24)   this.hr = hours; else   this.hr = 0; if ( minutes >= 0 && minutes < 60)   this.min = minutes; else   this.min = 0; if ( seconds >= 0 && seconds < 60)   this.sec = seconds; else   this.sec = 0; } // Note 01 Clock.prototype.setTime = setTime_Clock;
Note 01:
We declared a function setTime_Clock. Then we assign the function to the prototype object making a new method (setTime) that can be shared by all instance of the class type Clock.

6. Call the new Method from our Clock Object


myClock.setTime( 12, 12, 66);// Note 01: // Note 02: alert(myClock.hr);// returns 12 alert(myClock.min);// returns 12 alert(myClock.sec);// returns 0
Note 01:
The object instance myClock of class type Clock is using method setTime to reset the clocks time. Notice the invalid number for seconds in the calling statements actual parameter list. The method setTime will invalidate that number and return zero.
Note 02:
The object instance myClock had already been created before we added the method setTime to the prototype object. This is the beauty of prototype-based inheritance. We could have a thousand instances of the class type Clock, however, adding a property or method to the prototype will effect all instances. But it makes sense. Each individual instance does not own prototype properties (they inherit them). Prototype methods and properties exist in only one place and all instance share the prototype object.

7. Instance Methods


We have already built an instance method for our class type Clock. In step 5 above, we built the method "setTime". This is an instance method. If we were to instantiate more objects of the class type Clock, they all would share the "setTime" method.


8. Class Methods


// first declare the function // this function will look at two Clock objects and determine the Clock object with the latest time // two Clock object instances are passed to the function // the function returns the Clock with the latest time function latest_Clock( clock1, clock2 ) { if ( clock1.hr > clock2.hr )   return clock1; else if ( clock1.hr < clock2.hr )   return clock2;   if ( clock1.min > clock2.min )   return clock1; else if ( clock1.min < clock2.min )   return clock2;   if ( clock1.sec > clock2.sec )   return clock1; else return clock2; } // Note 01 Clock.latestTime = latest_Clock; // Note 02 var yourClock = new Clock( 8, 56, 22 ); // Note 03 var largest = Clock.latestTime(myClock, yourClock);
Note 01:
We declared a function latest_Clock. Then we assign the function to the class Clock making a new method (latestTime). We have just created a class method.
Note 02:
To compare the time of two objects, we need another object instance. We already have the Clock object "myClock". Here, we create a new instance of the class type Clock called, "yourClock".
Note 03:
Here we invoked the class method "latestTime". We pass it the two Clock instance objects. The method will return the object with the latest time.

9. Instance Properties


We have already built instance properties for our class type Clock. We did this in steps 1 and 2 above. First, we built a Clock constructor that initializes three properties (hr, min sec). To build actual instances, we must invoke the constructor. We did this in step 2. We invoked the Clock constructor passing it arguments that ultimately became instance properties of the myClock object.

JS provides three approaches for defining an instance property.

  1. Inside the constructor using the this keyword; applies to all objects instantiated by the class constructor.
  2. Inside the prototype object; applies to all objects instantiated for the related class.
  3. Inside an individual instance; applies to a single object.

10. Class Properties


// Note 01 Clock.daylightsavingstime = false; Clock.pst = true; // Note 02
Note 01:
Here we are defining two class properties. A boolean to indicate whether daylight savings is in effect. And another boolean to indicates whether pacific standard time is in effect.
Note 02:
If you define a property to the constructor function, you have built yourself a class property. The difference between a class property and an instance property is the class property is assigned to the class and the instance property is assigned to the object.

11. Multiple Constructors


Java allows for any class to have multiple constructors. Typically, each constructor has a unique version of the allowable formal parameter set. This allows a given constructor to initialize instance variables in a unique manner. Overloading occurs where the appropriate constructor is determined by the signature of the invoking statement.

With JavaScript, multiple constructors are not appropriate. If you define two functions with the same name in the same scope, the last function defined becomes the useable method. Method overloading is a mute point.

Given, we have already defined a constructor for class type Clock in step one above. If we define another constructor for class type Clock. The next instance of class type Clock will be initialized by the last function defined for class Clock.

// Note 01 function Clock( )// Note 02 { this.hr = 0; this.min = 0; this.sec = 0; }
Note 01:
Here is another constructor for the Clock class. This constructor takes no formal parameters. It therefore initializes the instance properties to zero.
Note 02:
The constructor has same class name "Clock".

If we instantiate a new Clock object, it's instance variables will be initialized to zero even if we pass the constructor actual parameters.

var aClock = new Clock( 9, 56, 22); alert(aClock.hr);// returns 0 alert(aClock.min);// returns 0 alert(aClock.sec);// returns 0

A final note; Native classes do appear to have multiple constructors because they can have multiple versions of the constructor call. For example, the Array Native class has three versions of the constructor call, all with a unique actual parameter set. But we do not know what the actual constructor function looks like. I suspect there is one constructor function that interrogates the parameters and determines how the instance properties should be initialized. This approach is feasible because of JavaScript's weakly typed data types.


12. Display the Property Names of an Object


Can't remember what your object's properties are called? Use the for/in statement.

// Note 01 function displayObjectPropertyNames(object) { var names = ""; for(property in object) names += property + "\n"; alert(names); } // Note 02
Note 01:
Define the function that will display the object's property names. You pass it the object.
Note 02:
The for/in statement builds a string with all the property names. The statement below will invoke the above function and pass it the myClock object. The above function will display the names of the three stance variables (hr, min, sec) via the alert function.
function displayObjectPropertyNames(myClock);

13. Delete a Property


You can delete a property from an object with the delete operator. The delete operator will not delete prototype properties or class properties. Only instance properties (and array elements) work with the delete operator.

delete myClock.sec;//the sec property is removed from the object

14. Methods Assigned to a Constructor


What happens when you define a function and then assign that function to a method inside a constructor?? In step five above we defined a function and then assigned it to the prototype object.

function setTime_Clock( hours, minutes, seconds) { if ( hours >= 0 && hours < 24)   this.hr = hours; else   this.hr = 0; if ( minutes >= 0 && minutes < 60)   this.min = minutes; else   this.min = 0; if ( seconds >= 0 && seconds < 60)   this.sec = seconds; else   this.sec = 0; }   Clock.prototype.setTime = setTime_Clock;

What if, instead of assigning the function to the prototype object, we assign the function inside the constructor like this:

function Clock(hours, minutes, seconds)// the constructor { this.hr = hours; this.min = minutes; this.sec = seconds; this.setTime = setTime_Clock; }

Now every object that is instantiated will own its own copy of method "setTime". This technique is permissible, but very inefficient. We can utilize our memory resource more wisely by assigning functions as methods of the prototype object. With prototype object methods, only one copy of the method exists in memory regardless of how many instances exist for class type Clock. All instances of class type Clock inherit the method "setTime".


15. Function Literal Example


This step is a simple illustration of how a function literal can be used to establish a new method for our class type Clock. First we show the same approach we used in step five above. In step five, we first declared the function and then assigned it to the prototype object as a new method. With a function literal, it can be accomplished with one statement.

// first the old way function getClockHour( ) { return this.hr; } //now assign the function to the prototype object Clock.prototype.getHour = getClockHour;

Now we will use a function literal and declare and assign in one statement.

Clock.prototype.getHour = function( ) { return this.hr; }



Top            

Rx4AJAX        About Us | Topic Index | Contact Us | Privacy Policy | 2008 This Site Built By PPThompson