Richard G Baldwin (512) 223-4758, baldwin@austin.cc.tx.us, http://www.austin.cc.tx.us/baldwin/

JavaScript Programming, Creating New Objects

Java/Web Programming, Lecture Notes # 2150, Revised 05/26/98.

Preface

The material was prepared as part of a new tutorial that I plan to publish on Web programming in general.  It is not part of the Java academic curriculum at ACC.

The purpose of this series of lessons is to teach you how to program in JavaScript.  The goal is to provide a programming tutorial that will be accessible to persons with no programming experience and will be equally useful to persons who already have programming experience using JavaScript or some other language.
 

Introduction

At this point, you have learned quite a lot about objects in JavaScript.  You have learned how to use the predefined objects such as Date.  You have learned how to instantiate new objects of the predefined object types.  You have learned how to access their properties and how to invoke their methods.  You have even learned how to add new properties to existing individual objects.

One important thing that you haven't learned yet is how to create your own object types and instantiate new objects from those types.  That is the primary subject of this lesson.
 

Creating New Object Types

JavaScript provides a number of predefined objects in two categories.  Some of those predefined objects, such as Date, are part of the core JavaScript language.  Others, such as History, are specific to Navigator.

You can also create your own object types and instantiate new objects from those types. There are essentially two ways to do this.

Before getting into the details on creating new object types, we need to discuss this which is a JavaScript keyword.
 

Using the this Keyword

C++, Java, and JavaScript all support the this keyword in similar ways.  Once an object type exists, it is possible to instantiate one or more instances or objects of that type.  If the object has one or more methods, then you can invoke one of the methods on a specific objects using syntax such as the following:
 
x1 = object1.getData();
x2 = object2.getData();
x3 = object3.getData();
 
As you can see, the same method can be invoked on many different objects of the same object type.  Frequently the code in the method needs to access the data contained in the specific object on which it was invoked, or for some other reason needs a reference to that specific object.  That is where the this keyword comes into play.

this is a special JavaScript keyword that you can use inside a method to refer to the specific object on which the method was invoked.  We will see examples of the use of this in the sample scripts in this lesson.
 

Using a Constructor Function

We will begin our study of creating new object types with the technique that has been around the longest and also which most closely mimics the techniques used in other object-oriented languages:  the constructor function.

You learned how to use the constructor function in earlier lessons to instantiate new objects from predefined object types using code such as the following:
 
newDateObject = new Date();
 
In particular, in one earlier lesson where we were using the predefined Date object, I mentioned that there were several available constructors for this object, with the different constructors initializing the new object in different ways.

Defining a new object type and creating a new object using a constructor involves two steps:

To define an object type, create a function for the object type that specifies its The sample script that follows illustrates how to define a new object type and instantiate multiple objects of that type.  The script also illustrates the use of the this keyword.

The following code fragment shows the constructor for this new object type named myObjectType.
 
      function myObjectType(intData, stringData){//constructor
        this.intData = intData;
        this.stringData = stringData;
      }//end constructor
 
I should point out that by general OOP standards, this constructor will result in a pretty crude object.  In fact, many OOP programmers wouldn't consider it to be an object at all.  In OOP, it is generally believed that an object should know how to manipulate its own data.  This requires that an object has methods.  So far, this object doesn't have any methods.  It only has data.  We will deal with methods in another script later in the lesson..

The next code fragment that we want to look at illustrates how this constructor can be used to instantiate one or more objects of the new type.  This code fragment instantiates two objects of the type and then accesses and displays the property values of each of the objects. (The function named d() is a general purpose display function.  You can see the code for this lesson in the complete listing of the script following this discussion.)
 
      obj1 = new myObjectType(5, "obj1");      
      obj2 = new myObjectType(10, "obj2");

      d("obj1 contains: ",obj1.intData," ",obj1.stringData);
      d("obj2 contains: ",obj2.intData," ",obj2.stringData);
 
The output from running this script is shown at the beginning of the complete listing that follows. As expected, the display reflects the data values stored in the objects when they were instantiated.
 
<!-- File Js00000420.htm
Copyright 1998, R.G.Baldwin 
This script is designed to illustrate defining and instantiating
new object types.

The output from running this script is:
obj1 contains: 5 obj1
obj2 contains: 10 obj2

Done.  
-------------------------------------------------------------------->
<HTML>
  <HEAD>
    <SCRIPT LANGUAGE="JavaScript1.2">
      <!-- Hide script

      function d(){//simple display function
        for(cnt = 0; cnt < d.length; cnt++)
          document.write(d[cnt]);//end for loop
        document.write("<BR>");//write a line break
      }//end function

      function myObjectType(intData, stringData){//constructor
        this.intData = intData;
        this.stringData = stringData;
      }//end constructor

      // End hiding  -->
    </SCRIPT> 
  </HEAD>

  <BODY>
    <SCRIPT>
      <!-- Hide script

      obj1 = new myObjectType(5, "obj1");      
      obj2 = new myObjectType(10, "obj2");

      d("obj1 contains: ",obj1.intData," ",obj1.stringData);
      d("obj2 contains: ",obj2.intData," ",obj2.stringData);


      // End hiding  -->
    </SCRIPT>

    <P> Done.
  </BODY>
</HTML>
.

Overloaded Constructors

When we were working with the predefined Date object type in earlier lessons, we mentioned that it has several different constructors.  In common OOP jargon, this would be referred to as overloaded constructors.

Also in an earlier lesson, we saw how it is possible to make use of the argument array to create a crude form of function overloading in JavaScript.  We can use that capability to create overloaded constructors for a new object type.

I do want to provide a cautionary note at this point.  The complexity of this approach could get out of hand very quickly.  This is particularly true in those cases where objects instantiated from the different versions of the constructors need to have methods with the same names and different behavior.  This would entail implementing function overloading within function overloading and, while possible, might be difficult to accomplish.

The next sample script upgrades the previous script to provide constructors that are overloaded to accommodate different numbers of parameters.

The structure of this overloaded constructor, at this point, is essentially the same as the overloaded function that we illustrated in a previous lesson.  We will upgrade it in a subsequent sample script.

The overloaded constructor function determines the length of the argument array whose name is the same as the name of the function, myObjectType.  A switch statement is used to select among three different blocks of code based on the length of that array (the number of parameters).

For the case of one parameter, the code stored the incoming parameter into one of the properties and initialized the other property with the string "Not initialized".

For the case of two parameters, the code stored the two incoming parameters in the two properties of the object.  Although it isn't necessary to require that all versions of the object have the same number and type of properties, this is probably a practical requirement later when time comes to provide methods that manipulate those properties.

For the case where the number of arguments was neither one nor two, an error message was displayed.

While an error message might be useful for human consumption, it probably isn't too useful for programming.  A better solution to this problem might be to cause the first two blocks of code to return true and cause the default code to return false.

Then the code that instantiates the object could test the return value to determine if the instantiation was or was not successful.  (Recall that I told you in the earlier lesson on function overloading that this is not a problem with other OOP languages such as C++ and Java.  Those languages would determine at compile time that the arguments being passed to the constructor don't match a valid constructor.)
 
      function myObjectType(){//constructor
        len = myObjectType.length;
        switch(len){
          case 1:
            this.intData = myObjectType[0];
            this.stringData = "Not initialized";
            break;
          case 2:
            this.intData = myObjectType[0];
            this.stringData = myObjectType[1];
            break;
          default:
            d("Not defined for ",len," parameters.");
        }//end switch
      }//end constructor
 
Code in a script in the body of the HTML document instantiates two objects using the two valid constructors and attempts to instantiate a third by calling the constructor with too many parameters. This third attempt is not successful and an error message is produced.

Then the properties of the two valid objects are displayed.
 
      obj1 = new myObjectType(5);      
      obj2 = new myObjectType(10, "obj2");
      obj3 = new myObjectType(10, "obj3", "Third parameter");
 
The output from running this script is shown in the comments at the beginning of the listing which follows.
 
<!-- File Js00000430.htm
Copyright 1998, R.G.Baldwin 
This script is designed to illustrate a crude form of 
overloaded constructors.

The output from running this script is:
Not defined for 3 parameters.
obj1 contains: 5 Not initialized
obj2 contains: 10 obj2

Done.
-------------------------------------------------------------------->
<HTML>
  <HEAD>
    <SCRIPT LANGUAGE="JavaScript1.2">
      <!-- Hide script

      function d(){//simple display function
        for(cnt = 0; cnt < d.length; cnt++)
          document.write(d[cnt]);//end for loop
        document.write("<BR>");//write a line break
      }//end function

      function myObjectType(){//constructor
        len = myObjectType.length;
        switch(len){
          case 1:
            this.intData = myObjectType[0];
            this.stringData = "Not initialized";
            break;
          case 2:
            this.intData = myObjectType[0];
            this.stringData = myObjectType[1];
            break;
          default:
            d("Not defined for ",len," parameters.");
        }//end switch
      }//end constructor

      // End hiding  -->
    </SCRIPT> 
  </HEAD>

  <BODY>
    <SCRIPT>
      <!-- Hide script

      obj1 = new myObjectType(5);      
      obj2 = new myObjectType(10, "obj2");
      obj3 = new myObjectType(10, "obj3", "Third parameter");

      d("obj1 contains: ",obj1.intData," ",obj1.stringData);
      d("obj2 contains: ",obj2.intData," ",obj2.stringData);


      // End hiding  -->
    </SCRIPT>

    <P> Done.
  </BODY>
</HTML>
.

Objects as Properties

The properties of an object are not restricted to simply numeric, string, and boolean values.  Rather, they can be other objects just as well.  This is illustrated in the following sample script where an object of the predefined object type named Date is passed to the constructor for a new object type named myObjectType.

The constructor for this new object type looks just like the constructor for our previous definitions of new object types.  The constructor simply uses this to save the incoming parameters, including the date object, in a variable of the new object.
 
      function myObjectType(theString,theDate){//constructor
        this.theString = theString;
        this.theDate = theDate;
      }//end constructor
 
The difference resulting from having properties which are themselves objects arises in the next fragment where information is being extracted from the properties of the new object.  Since one of the properties is itself an object, a two level extraction process in involved.

Note in particular the highlighted portion of this fragment which reads obj.theDate.getMonth().  Note that this expression contains two periods whereas before we have seen the use of only one period in expressions similar to this one.  In this case, the following expression (note that this is only part of the overall expression)

obj.theDate

extracts the Date object from the object named obj.  The Date object then replaces the first two terms in the overall expression providing a result that is analogous to the following expression (that never really exists).

(the date object).getMonth()

At this point in the execution of the script, we have the method named getMonth() being invoked on the date object that was fetched by the first two terms in the expression.  This returns the month portion of the date contained in the Date object which is passed to the method named d() for display.
 
      obj = new myObjectType("Dick Baldwin", new Date());
      d(obj.theString," Month number ",obj.theDate.getMonth());
 
The Date object is constructed anonymously in the above instantiation of obj by including the new operator and the call to the Date constructor in the argument list of the constructor for obj.  It would have been equally valid to first construct the Date object and assign it to a variable and then pass that variable to the constructor for obj.

The output from running this script is shown at the beginning of the listing that follows.
 
<!-- File Js00000440.htm
Copyright 1998, R.G.Baldwin 
This script is designed to illustrate the use of objects as
properties of another object.

The output from running this script is:
Dick Baldwin Month number 4

Done. 
-------------------------------------------------------------------->
<HTML>
  <HEAD>
    <SCRIPT LANGUAGE="JavaScript1.2">
      <!-- Hide script

      function d(){//simple display function
        for(cnt = 0; cnt < d.length; cnt++)
          document.write(d[cnt]);//end for loop
        document.write("<BR>");//write a line break
      }//end function

      function myObjectType(theString,theDate){//constructor
        this.theString = theString;
        this.theDate = theDate;
      }//end constructor

      // End hiding  -->
    </SCRIPT> 
  </HEAD>

  <BODY>
    <SCRIPT>
      <!-- Hide script

      obj = new myObjectType("Dick Baldwin", new Date());
      d(obj.theString," Month number ",obj.theDate.getMonth());

      // End hiding  -->
    </SCRIPT>

    <P> Done.
  </BODY>
</HTML>
 
We learned and demonstrated in an earlier lesson that you can add new properties to an object after it is instantiated.  We demonstrated this capability using one of the predefined object types. However, this capability is not restricted to predefined object types.  We could just as easily add a new property to an existing object of a new object type that we define using the same same procedure for adding the property that we used before.
 

Methods

A method is a function associated with an object. You define a method the same way you define a standard function (except that you will probably make use of this which you don't use in standard functions). Once you have the definition for the method, you can associate it with an object in either of two ways: We will see examples of both approaches in this section.
 

Adding Methods to Objects

The following sample script illustrates adding a method to an existing object.  We begin with a fragment showing the constructor for a new object type named newType.  This is a "plain vanilla" constructor and you should understand it without further explanation by now.
 
      function newType(theString,theDate){//constructor
        this.theString = theString;
        this.theDate = theDate;
      }//end constructor
 
The next fragment is the definition of a function that will be associated with an object instantiated using the above constructor.  This function may at first appear to be similar to others that you have seen in previous lessons.  It is designed to extract the necessary information from a Date object and display the current date and time.

However, this function is significantly different from others like it that you have seen previously.  The difference has to do with how the the function gains access to the Date object from which it will extract the information.  In this case, it was necessary to plan this function in advance as one that would become a method of an object of type newType.  Having determined this, it was obvious where the Date object would come from.  It would be a property of an object of type newType.

Since the Date object will be a property of an object, and this function will be a method of the same object, the code in the function can access the Date object using this.  However, the code in the function also has to know the name of the property that represents the Date object.  So, you will see several expressions in the following code similar to this.theDate.getDate().

Technically, any function could be added to an existing object and considered to be a method of the object.  However, it is important to realize that not just any function can be added to an object to become a useful method of that function.  Because of names and other considerations, if the method is to be able to access the properties of the object, or any other data stored in the object, that must be taken into account when the function is written.
 
      function showDate(){
        d("The string is ",this.theString);                  
        theMonth = this.theDate.getMonth() + 1;      
        theDay = this.theDate.getDate();
        theYear = this.theDate.getYear();
        theHour = this.theDate.getHours();
        if(theHour > 12){
          theHour -= 12;
          amPm = " PM";
        }else amPm = " AM";
        theMin = this.theDate.getMinutes();
        d("The date and time is ",theHour,":",theMin,amPm,
                            " on ",theMonth,"/",theDay,"/",theYear);
      }//end function showDate()
 
The following code fragment

The instantiation of the object, and the invocation of the method on the object should be familiar to you by now.  However, pay particular attention to the syntax used to add the method to the object. Note that this statement references the name of the method and the name of the function without any parentheses.
 
      obj = new newType("Dick Baldwin", new Date());//create object
      obj.showDate = showDate;//add method to the object
      obj.showDate();//invoke the method on the object
 
Note also that this code causes the name of the method and the name of the function to be the same, but that is not a requirement.  The following code would have worked just as well where a new name is given to the method when it defined to be an existing function.
 
      obj = new newType("Dick Baldwin", new Date());//create object
      obj.theMethod = showDate;//add method to the object
      obj.theMethod();//invoke the method on the object
 
The output from running this script is shown at the beginning of the listing of the script that follows.
 
<!-- File Js00000450.htm
Copyright 1998, R.G.Baldwin 
This script is designed to illustrate adding a method to an
existing object.

The output from running this script is:
The string is Dick Baldwin
The date and time is 9:56 AM on 5/26/98

Done. 
-------------------------------------------------------------------->
<HTML>
  <HEAD>
    <SCRIPT LANGUAGE="JavaScript1.2">
      <!-- Hide script

      function d(){//simple display function
        for(cnt = 0; cnt < d.length; cnt++)
          document.write(d[cnt]);//end for loop
        document.write("<BR>");//write a line break
      }//end function

      function newType(theString,theDate){//constructor
        this.theString = theString;
        this.theDate = theDate;
      }//end constructor

      function showDate(){
        d("The string is ",this.theString);                  
        theMonth = this.theDate.getMonth() + 1;      
        theDay = this.theDate.getDate();
        theYear = this.theDate.getYear();
        theHour = this.theDate.getHours();
        if(theHour > 12){
          theHour -= 12;
          amPm = " PM";
        }else amPm = " AM";
        theMin = this.theDate.getMinutes();
        d("The date and time is ",theHour,":",theMin,amPm,
                            " on ",theMonth,"/",theDay,"/",theYear);
      }//end function showDate()

      // End hiding  -->
    </SCRIPT> 
  </HEAD>

  <BODY>
    <SCRIPT>
      <!-- Hide script

      obj = new newType("Dick Baldwin", new Date());//create object
      obj.showDate = showDate;//add method to the object
      obj.showDate();//invoke the method on the object

      // End hiding  -->
    </SCRIPT>

    <P> Done.
  </BODY>
</HTML>
.

Including Methods in Constructors

Adding a method to an existing object causes that method to be usable with only that one object.  You can also define methods for an object type by including the method definition in the object constructor function. If you do this, the method will apply to all objects of the type, and you won't need to add the method to the individual objects after they are instantiated.

The following sample script is a little more elaborate than the previous one.  In addition to providing the method definition in the constructor, it also provides two different constructors for two different object types.  These two constructors each define a method, and they share the same actual function for that method.

The following fragment shows the first of two constructors.  This is the constructor for an object type named NewType.  Other than the method definition, there is nothing new here.

Pay particular attention to the syntax of the method definition for a method named theMethod that is highlighted in boldface.  Note that this statement refers to a method and a function but there are no parentheses in this statement.

This statement says that this object has a method named theMethod() which is actually implemented by making a call to the function named showDate().  Any parameters that are passed to theMethod() will be automatically passed to showDate() (although there aren't any parameters in this sample script).  The system probably treats theMethod simply as an alias for showDate but I don't know that for sure.
 
      function NewType(theString,theDate){
        this.theString = theString;
        this.theDate = theDate;
        this.theMethod = showDate;
      }//end constructor
 
The next fragment is the constructor for another object type named AnotherNewType. This constructor differs from the previous one in that it takes three parameters instead of just two.  However, one of the parameters is a Date object just as in the previous case.  This is important with respect to the method that is defined.

The most important thing about this constructor is that it also defines a method and shares the showDate() function with the previous constructor.  This illustrates that constructors can share functions for use as methods provided that the behavior of the function is appropriate for objects of all the types that share it.
 
      function AnotherNewType(theString,anotherString,theDate){
        this.theString = theString;
        this.anotherString = anotherString;
        this.theDate = theDate;
        this.theMethod = showDate;
      }//end constructor
 
The function that is shared by the two constructors is shown in the following box.  This is essentially the same function as in the earlier sample script except that I removed the statement having to do with the string property.  In particular, this function now deals only with an object of type Date, making it compatible with both constructors.  Each constructor has a property that is an object of type Date, and the name of the property is the same in both cases.  This requirement for common names is very restrictive.
 
      function showDate(){
        theMonth = this.theDate.getMonth() + 1;      
        theDay = this.theDate.getDate();
        theYear = this.theDate.getYear();
        theHour = this.theDate.getHours();
        if(theHour > 12){
          theHour -= 12;
          amPm = " PM";
        }else amPm = " AM";
        theMin = this.theDate.getMinutes();
        d("The date and time is ",theHour,":",theMin,amPm,
                            " on ",theMonth,"/",theDay,"/",theYear);
      }//end function showDate()
 
Finally, the following fragment was extracted from a script in the body of the HTML page.  The code in this fragment instantiates one object of each type and then invokes the method to display the Date information in each object.
 
      //Instantiate object of one type
      obj1 = new NewType("Dick Baldwin", new Date());
      d(obj1.theString);//display a property of the object
      obj1.theMethod();//invoke the method on the object

      //Instantiate an object of another type
      obj2 = new AnotherNewType("Tom Jones","Sue Smith",new Date());
      d(obj2.theString," ",obj2.anotherString);//display properties
      obj2.theMethod();//invoke the method on the object
 
The output from running this script is shown at the beginning of the listing of the script that follows.
 
<!-- File Js00000460.htm
Copyright 1998, R.G.Baldwin 
This script is designed to illustrate inclusion of methods in the
defintion of a constructor function.

The output from running this script is:
Dick Baldwin
The date and time is 10:56 AM on 5/26/98
Tom Jones Sue Smith
The date and time is 10:56 AM on 5/26/98

Done. 
-------------------------------------------------------------------->
<HTML>
  <HEAD>
    <SCRIPT LANGUAGE="JavaScript1.2">
      <!-- Hide script

      function d(){//simple display function
        for(cnt = 0; cnt < d.length; cnt++)
          document.write(d[cnt]);//end for loop
        document.write("<BR>");//write a line break
      }//end function

      //One constructor
      function NewType(theString,theDate){
        this.theString = theString;
        this.theDate = theDate;
        this.theMethod = showDate;
      }//end constructor

      //Another constructor
      function AnotherNewType(theString,anotherString,theDate){
        this.theString = theString;
        this.anotherString = anotherString;
        this.theDate = theDate;
        this.theMethod = showDate;
      }//end constructor

      //Shared function
      function showDate(){
        theMonth = this.theDate.getMonth() + 1;      
        theDay = this.theDate.getDate();
        theYear = this.theDate.getYear();
        theHour = this.theDate.getHours();
        if(theHour > 12){
          theHour -= 12;
          amPm = " PM";
        }else amPm = " AM";
        theMin = this.theDate.getMinutes();
        d("The date and time is ",theHour,":",theMin,amPm,
                            " on ",theMonth,"/",theDay,"/",theYear);

      }//end function showDate()

      // End hiding  -->
    </SCRIPT> 
  </HEAD>

  <BODY>
    <SCRIPT>
      <!-- Hide script

      //Instantiate object of one type
      obj1 = new NewType("Dick Baldwin", new Date());
      d(obj1.theString);//display a property of the object
      obj1.theMethod();//invoke the method on the object

      //Instantiate an object of another type
      obj2 = new AnotherNewType("Tom Jones","Sue Smith",new Date());
      d(obj2.theString," ",obj2.anotherString);//display properties
      obj2.theMethod();//invoke the method on the object

      // End hiding  -->
    </SCRIPT>

    <P> Done.
  </BODY>
</HTML>
 .
 
 
Caution:  While working with the next sample script, I noticed that the algorithm that I have been using throughout this tutorial to convert time from the Date object into AM/PM representation isn't correct for the hour immediately following 12:00 noon.  This hour is reported as being AM when it should be PM.  If you adopt this algorithm for your own use, be sure to modify it to correct this bug. 
 
 
While we are at this point, there is one more thing that we need to confirm.  When we invoke a method on an object, and the method accesses the properties of the object, it is very important that it accesses the properties of the object on which it was invoked and not the properties of some other object of the same or a different type.

We need to confirm that we can instantiate multiple objects of  the same type, all of which have the same method based on the same function, and the method will treat the data in each object independently of the other objects. That confirmation is provided in the following sample script.
 
This script defines an object constructor that has a method very similar to the previous script.  Therefore, we won't show that part of the script in these fragments.  You can see the constructor in context in the listing of the script that follows this discussion.

The following fragment shows the instantiation and display of the contents of two objects of the same type:  obj1 and obj2.

After the first object was instantiated and displayed, a delay was forced into the script to allow the clock to turn over before instantiating the next object.  This was done to cause the contents of the Date object to be different between the two object.

After the second object was instantiated, its contents were displayed.  Then the contents of the first object were displayed again to confirm that they had not been corrupted by some unplanned interaction with the second object.
 
      d("Instantiate and display first object");
      obj1 = new NewType("First Object", new Date());
      d(obj1.theString);//display a property of the object
      obj1.theMethod();//invoke the method on the object

      d("Force a delay to let the clock turn over");
      for(cnt1 = 200000; cnt1 > 0; cnt1--){
        dummy = 0;
      }//end for loop<BR>

      d("Instantiate and display second object");
      obj2 = new NewType("Second Object", new Date());
      d(obj2.theString);//display a property of the object
      obj2.theMethod();//invoke the method on the object

      d("Display first object again");
      d(obj1.theString);//display a property of the object
      obj1.theMethod();//invoke the method on the object
 
The behavior of the script to maintain the two objects of the same type as completely separate entities is demonstrated by the output from the program that appears at the beginning of the following listing.

This output shows that instantiating and manipulating a second object of the same type did not corrupt the data stored in the properties of the first object.
 
<!-- File Js00000470.htm
Copyright 1998, R.G.Baldwin 
This script is designed to illustrate inclusion of methods in the
definition of a constructor function and the instantiation and
use of multiple objects of that type..

The output from running this script is:
Instantiate and display first object
First Object
The date and time is 12:45 AM on 5/26/98
Force a delay to let the clock turn over
Instantiate and display second object
Second Object
The date and time is 12:46 AM on 5/26/98
Display first object again
First Object
The date and time is 12:45 AM on 5/26/98

Done.
-------------------------------------------------------------------->
<HTML>
  <HEAD>
    <SCRIPT LANGUAGE="JavaScript1.2">
      <!-- Hide script

      function d(){//simple display function
        for(cnt = 0; cnt < d.length; cnt++)
          document.write(d[cnt]);//end for loop
        document.write("<BR>");//write a line break
      }//end function

      //constructor
      function NewType(theString,theDate){
        this.theString = theString;
        this.theDate = theDate;
        this.theMethod = showDate;
      }//end constructor

      function showDate(){
        theMonth = this.theDate.getMonth() + 1;      
        theDay = this.theDate.getDate();
        theYear = this.theDate.getYear();
        theHour = this.theDate.getHours();
        if(theHour > 12){
          theHour -= 12;
          amPm = " PM";
        }else amPm = " AM";
        theMin = this.theDate.getMinutes();
        d("The date and time is ",theHour,":",theMin,amPm,
                            " on ",theMonth,"/",theDay,"/",theYear);
      }//end function showDate()

      // End hiding  -->
    </SCRIPT> 
  </HEAD>

  <BODY>
    <SCRIPT>
      <!-- Hide script

      d("Instantiate and display first object");
      obj1 = new NewType("First Object", new Date());
      d(obj1.theString);//display a property of the object
      obj1.theMethod();//invoke the method on the object

      d("Force a delay to let the clock turn over");
      for(cnt1 = 200000; cnt1 > 0; cnt1--){
        dummy = 0;
      }//end for loop<BR>

      d("Instantiate and display second object");
      obj2 = new NewType("Second Object", new Date());
      d(obj2.theString);//display a property of the object
      obj2.theMethod();//invoke the method on the object

      d("Display first object again");
      d(obj1.theString);//display a property of the object
      obj1.theMethod();//invoke the method on the object

      // End hiding  -->
    </SCRIPT>

    <P> Done.
  </BODY>
</HTML>
.

Adding Properties to an Object Type

In an earlier lesson, we learned how to add a property to an existing object.  That process added the new property only to a specific object or instance of the type.  It did not change the basic type definition so as to cause all objects of the type to have the new property.

In this section, we will learn how to add a new property to an existing object type, meaning to change the basic type definition to include the new property.  This will effect all objects of the type including all existing objects of the type..

This script begins with an ordinary constructor to define a new object type named NewType that has two properties:

There is nothing particularly interesting about the script at this point. The script doesn't become really interesting until we add a new property to the object type as shown in a later fragment.
 
      function NewType(theString,theInt){
        this.theString = theString;
        this.theInt = theInt;
      }//end constructor
 
The next fragment was extracted from a section of script in the body of the HTML document.  The script begins by instantiating and displaying the contents of three objects of type NewType.  This is still completely "plain vanilla."  There is nothing to get excited about yet.
 
      d("Instantiate and display first object");
      obj1 = new NewType("First ", true);
      d(obj1.theString,obj1.theInt);

      d("Instantiate and display second object");
      obj2 = new NewType("Second ", false);
      d(obj2.theString,obj2.theInt);

      d("Instantiate and display third object");
      obj3 = new NewType("Third ", true);
      d(obj3.theString,obj3.theInt);
 
Now the fun begins.  At this point, we add a new property named newProperty to the NewType object type.  This effects all existing and future objects of the NewType type.  In effect, this modifies the definition of the type, retroactively, so as to include all previously instantiated objects of the type that are still in existence.  This is pretty powerful stuff.

This is accomplished using the following statement.  Note in particular the syntax of this statement and the use of the prototype property.

In addition to adding the new property to all objects of this type, this statement also initializes that property to null in all existing objects.
 
      NewType.prototype.newProperty = null;
 
To make certain that everything worked as planned, we populate the new property in two of the three existing objects with numeric values.  However, we don't populate the third object which means that the new property in this object should have a value of null.

Here we want to make a distinction between null and undefined.  To accomplish this, we display all three properties in all three objects and also attempt to display the contents of another property named junk that has never been defined.  If everything goes according to plan, the junk property should show to be undefined in all objects.  The newProperty property should have values of 3.14 and 6.28 in the first two objects respectively and null in the third object.
 
      obj1.newProperty = 3.14;
      obj2.newProperty = 6.28;

      d(obj1.theString,obj1.theInt," ",obj1.newProperty," ",obj3.junk);
      d(obj2.theString,obj2.theInt," ",obj2.newProperty," ",obj3.junk);
      d(obj3.theString,obj3.theInt," ",obj3.newProperty," ",obj3.junk);
 
The output from running the script is shown at the beginning of the following listing of the script.  This output confirms that everything went as expected.
 
<!-- File Js00000480.htm
Copyright 1998, R.G.Baldwin 
This script is designed to illustrate the addition of a new 
property to an object type, thereby changing the basic
definition of the type.

The output from running this script is:
Instantiate and display first object
First true
Instantiate and display second object
Second false
Instantiate and display third object
Third true
Add a new property to NewType and initialize to null.
Populate two objects, display all three.
Try to display undefined property on all objects.
First true 3.14 undefined
Second false 6.28 undefined
Third true null undefined

Done.
-------------------------------------------------------------------->
<HTML>
  <HEAD>
    <SCRIPT LANGUAGE="JavaScript1.2">
      <!-- Hide script

      function d(){//simple display function
        for(cnt = 0; cnt < d.length; cnt++)
          document.write(d[cnt]);//end for loop
        document.write("<BR>");//write a line break
      }//end function

      //constructor
      function NewType(theString,theInt){
        this.theString = theString;
        this.theInt = theInt;
      }//end constructor

      // End hiding  -->
    </SCRIPT> 
  </HEAD>

  <BODY>
    <SCRIPT>
      <!-- Hide script

      d("Instantiate and display first object");
      obj1 = new NewType("First ", true);
      d(obj1.theString,obj1.theInt);

      d("Instantiate and display second object");
      obj2 = new NewType("Second ", false);
      d(obj2.theString,obj2.theInt);

      d("Instantiate and display third object");
      obj3 = new NewType("Third ", true);
      d(obj3.theString,obj3.theInt);

      d("Add a new property to NewType and initialize to null.");
      d("Populate two objects, display all three.");
      d("Try to display undefined property on all objects.");
      NewType.prototype.newProperty = null;
      obj1.newProperty = 3.14;
      obj2.newProperty = 6.28;

      d(obj1.theString,obj1.theInt," ",obj1.newProperty," ",obj3.junk);
      d(obj2.theString,obj2.theInt," ",obj2.newProperty," ",obj3.junk);
      d(obj3.theString,obj3.theInt," ",obj3.newProperty," ",obj3.junk);


      // End hiding  -->
    </SCRIPT>

    <P> Done.
  </BODY>
</HTML>
.

Object Initializers

Prior to JavaScript V1.2, you could only instantiate objects by applying the new operator to the constructor, or invoking some other function or method that did that on your behalf.

JavaScript 1.2 provides another way to instantiate objects.  If you only need one object of a newly defined object type, and don't need to make provisions for instantiating additional objects of that type, an object initializer may be an appropriate way to go.

The syntax for creating an object using an object initializer is:
 
objectName = {property1:value1, property2:value2,..., propertyN:valueN}
 
where:

According to Netscape, the objectName and assignment is optional. If you do not need to refer to this object elsewhere, you do not need to assign it to a variable  (it can be an anonymous object).

The following statement would create a simple object named myObj having three properties named who, what, and where.  The initial values of the three properties are respectively:  "Sue", "went", and "home".
 
myObj = {who:"Sue", what:"went", where:"home"}
 
It is also possible to nest objects when defining them in this way.  The following statement upgrades the previous one such where where is an object property having properties morning and evening with values of "work" and "home" respectively.
 
myObj = {who:"Sue", what:"went", where:{morning:"work",evening:"home"}}
 
The Netscape documentation that I have seen doesn't address the question of creating methods for objects that are instantiated in this fashion.  However, one might reasonably assume that once the object exists, a method could be added to the object just the same as if the object had been created using a constructor.

Array Initializers

In an earlier lesson, we learned how to create arrays by instantiating objects of type Array.  At that time I told you that in JavaScript 1.2 there is an alternative method for creating arrays:  Array Initializers.

An array Initializer allows you to create arrays in ways similar to the creation of objects using object initializers.  The syntax for creating an array using an array initializer is as shown below
 
arrayName = [element0, element1, ..., elementN]
 
where

The array is initialized with the specified values as its elements, and its length is set to the number of arguments.

Assigning the array to a variable name is optional.

You are not required to specify all of the elements in the array, but if you leave out any element specifications, you must provide the commas anyway to serve as placeholders.  In this case, the value of the elements that you don't specify are undefined.

-end-