Chapter 4

Using Built-In Objects and Custom Objects


CONTENTS

You learned about the basic principles of object-oriented JavaScript programming in Chapter 3 "Working with Objects and Events." This chapter goes into detail about the techniques used in object-oriented programming. You will also explore the built-in objects you can use to make JavaScript programming easier, and learn about these objects using several example programs.

Techniques for Object-Oriented Programming

To continue the discussion of object-oriented JavaScript programming, let's look at the keywords and terms JavaScript uses to represent objects and other object-oriented concepts, and the ways you can use them. This will give you a foundation to understand the built-in objects, which are introduced in the next section.

Using Objects, Properties, and Methods

The basic component of object-oriented programming is, of course, an object. You can define objects by creating a function to define them, as you learned in Chapter 3. For example, this function defines the Card object, which you worked with in Chapter 3:

function Card(name,address,work,home) {
   this.name = name;
   this.address = address;
   this.work_phone = work;
   this.home_phone = home;
   this.PrintCard = PrintCard;

}

This function simply defines the name of the object type and assigns values to each of its functions. It also assigns the name of a function (PrintCard) as a method of the Card object.

You can use any variable as a property of an object-in fact, you can use another object as a property. For example, suppose you defined an Address object to hold the different components of an address:

function Address(street1, street2, city, state, zip) {
   this.street1 = street1;
   this.street2 = street2;
   this.city = city;
   this.state = state;
   this.zip = zip;

}

Because JavaScript doesn't require that you specify variable types, you don't need to change the definition for the Card object. It already expects an address and assigns it to the address property. You can assign an object to this property just as easily. Here is an example:

tomaddr = new Address("123 Elm Street", "Apartment 312", "Ogden", "UT",
 "84404");
tom = new Card("Tom Smith", tomaddr, "555-1239", "555-2394");

Here you have defined an Address object called tomaddr to hold Tom's address. Next, you create the Card object called tom. As the address parameter, you specify the name of the Address object.

You now have an object within an object-the tomaddr Address object is a property, or child object, of the tom Card object. The syntax for accessing these properties is simply to list both objects separated by periods. For example, if you need to assign a variable to Tom's zip code, you could use this statement:

z = tom.address.zip;

An object used as a property can have methods also. For example, you could define a PrintAddress() method for the Address object that prints each field of the address:

function PrintAddress() {
   document.write("Address:\n");
   document.write(this.street1, "\n");
   document.write(this.street2, "\n");
   document.write(this.city, "\n");
   document.write(this.state, "\n");
   document.write(this.zip, "\n");
}

You would then link this function as a method of the Address object by adding this statement to the Address object's definition:

this.PrintAddress = PrintAddress;

You could then access this method for Tom's address:

tom.address.PrintAddress();

Methods can also be used within other methods. For example, you could expand the PrintCard() method to print all the address fields by calling the PrintAddress() method:

function PrintCard() {
   document.write("Name: ", this.name, "\n");
   this.address.PrintAddress();
   document.write("Work Phone: ", this.work_phone, "\n");
   document.write("Home Phone: ", this.home_phone, "\n");
}

This is the syntax you will use any time an object is used as a property of another object. You will see in Chapter 5 "Accessing Window Elements as Objects," that the built-in objects used to represent parts of the browser's display and the Web page use this technique frequently.

The new Keyword

I used the new keyword several times in the previous examples to create new objects. In object-oriented terms, you are actually creating an instance of an object class. Any variable you create with the new keyword is an instance of that object. The object definition itself is referred to as the object class, or the object type.

With some built-in objects, such as the String object, you don't need to use the new keyword; you simply define a string variable, and JavaScript creates a String object automatically. There are other built-in objects with which you can use new.

The this Keyword

The this keyword has appeared in most of the examples. It is simply a shorthand for "the current object." This is usually used in object definitions, where it refers to the object being defined, and in method definitions, where it refers to the object the method is acting on. It can also be used in event handlers, as you'll see in Chapter 5.

The with Keyword

The with keyword is one you haven't seen before. You can use it to make JavaScript programming easier-or at least easier to type.

The with keyword specifies an object, and it is followed by a set of statements enclosed in braces. For each statement in the set, any properties you mention without specifying an object are assumed to be for that object.

As an example, suppose you used the Address object definition given earlier to create an address object called Fred. You could then use the following statements to assign values to the Address object's properties:

with (Fred) {
   street1= "12 E 400 S";
   street2= "Suite 200";
   city="Beverly Hills";
   state="CA";
   zip="90210"

}

This enables you to avoid typing the object's name (Fred) at the beginning of each property name: Fred.street1, Fred.street2, and so forth.

Obviously, the with keyword only saves a bit of typing in situations like this. However, you will find it very useful when you're dealing with an object throughout a large procedure, or when you are using a built-in object, such as the Math object.

Creating a Generic Object

Because JavaScript objects are so flexible, you may wonder why the constructor function is necessary at all. As a matter of fact, you can create an object without one by using the Object() constructor. For example, this statement creates an object called data:

data = new Object();

Because it isn't any particular kind of object yet, I call it a generic object. You can add properties to the object in the usual fashion. This is particularly handy when you are using the object as an associative array; you'll look at this technique in Chapter 10, "Working with Multiple Pages and Data."

Looping Through an Object's Properties

The final statement used for object-oriented work in JavaScript is the for...in loop, which you looked at briefly in Chapter 3. This loop executes once for each property of an object, assigning the index variable to the property name. For example, you could make a simple function to list the properties of an object and their values, as in List-ing 4.1.


Listing 4.1. A simple example of a for...in loop.
function list(object) {
   for (var i in object) {
      document.write("Property: ",i," Value: ",object[i], "<BR>");
   }
}

This function uses the variable i to iterate through the object's properties and uses the document.write() function to display the property name and the value.

Note
Notice that I used the syntax object[i] to refer to the property of the object in the previous example. It may seem more obvious to use object.i to refer to the property, but this won't work-JavaScript will interpret this as asking for a property called i. In order to use the value of i, you need to use brackets.

Using Built-In Objects

JavaScript includes several built-in objects. They are not part of the object hierarchy, and they do not represent any part of a Web page. Instead, they are used for programming functions. These include the following:

You will look at each of these types of objects in detail in the next sections.

Using Array Objects

Chapter 2 "Working with Larger Programs and Variables," introduced the Array object briefly. The original version of JavaScript did not include arrays, but they are now a built-in feature. You can create a new Array object to define an array. (Unlike other variables, arrays must be declared.) Use the new keyword to define an array:

students = new Array(30);

This example creates an array with 30 elements, numbered 0 through 29. You can use these values by addressing their array index:

students[29]="Phred Madsen";

This refers to the last element of the array, index 29.

Array objects have a single property, length. This provides the number of elements in the array, usually the same number with which you declared the array. In the array declared in the previous example, students.length would return 30.

Note
When you define an array, its elements are filled with null, or undefined values, up to the length you specify. You can dynamically change an array's size by assigning to the length property.

In addition, the array object has three methods:

You will see examples of these methods throughout this book; for example, in Chapter 15, "Real-Life Examples III," the sort() method is used to score poker hands. You will also look at a simple example in the next section.

Creating an Array

Before continuing, let's explore an example of using an Array object with some of the array methods. Look at the JavaScript program shown in Listing 4.2.


Listing 4.2. Use of the Array object and its methods.
// Room for 3 items (0-2)
groceries = new Array(3);
groceries[0]="dental floss";
groceries[1]="baby powder";
groceries[2]="clam chowder";
document.writeln(groceries.join());
document.writeln(groceries.reverse().join());
document.writeln(groceries.sort().join());

This defines an array called groceries, able to hold 3 items. Next, you assign values to three of the items. You can then observe the Array object methods in action with three document.writeln statements:

Using String Objects

You've already used String objects; any string variable in JavaScript is actually a String object. You learned about this object briefly in Chapter 3. String objects have a single property, length. They also have a variety of methods that you can use to perform string functions.

The methods of the String object enable you to convert strings, work with pieces of strings, search for values, control the string's appearance on the HTML page, and control HTML links and anchors. You'll look at these by category in the next sections.

Note
You don't have to create a string variable to use the String object methods; you can use them on any object with a string value. This includes the text-valued properties of any of the objects in the Web page object hierarchy.

String Conversions

Two methods of the String object enable you to convert the contents of the string easily to all uppercase or all lowercase:

For example, the following statement displays the value of the text string variable in lowercase:

document.write(text.toLowerCase());

Note that the statement doesn't change the value of the text variable. These methods return the upper- or lowercase version of the string, but they don't change the string itself. All of the methods of the String object work in this manner.

One other conversion method is the toString() method. This one is a bit odd-it can be used with non-string objects. It is used to explicitly convert them to strings. For example, if a is a numeric variable containing the number 500, a.toString() would return the string "500".

Working with Substrings

Three important String object methods enable you to work with substrings, or portions of strings. These methods are useful when you need to split a string into components or test portions of the string one at a time.

The first of these is the substring() method. This returns a string consisting of a portion of the original string between two index values, which you must specify in parentheses. For example, the following displays the fourth through sixth characters of the text string:

document.write(text.substring(3,6));

So where do the 3 and the 6 come from? No, there is no typo. There are three things you need to know about the index parameters:

As another example, suppose you defined a string called alpha to hold the alphabet:

alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

The following are examples of the substring() method using this string:

The second method for working with substrings is the charAt() method. This method is simpler: it takes a single index, and returns a single character. Here are a few examples using the alpha string defined previously:

The final method for working with parts of strings is probably the most powerful. The split() method splits a string into an array of strings, based on a separator you specify. For example, the following statement splits the components of a name divided by spaces:

nn = "John Q. Public".split(" ");

After this statement, the nn array will contain three elements: nn[0] is "John", nn[1] is "Q.", and nn[2] is "Public". This method is useful any time you need to process a list of items.

Searching a String

The indexOf() method searches for a string within another string. Use the string you wish to search for the method call and specify the string to be searched for in the parentheses. This example searches for "text" in the temp String object:

location = temp.indexOf("text");

The value returned to the location variable is an index into the string, similar to the first index in the substring() method. The first character of the string is index zero.

You can specify an optional second parameter to indicate the index value to begin the search. For example, this statement searches for the word "fish" in the temp string, starting with the 20th character:

location = temp.indexOf("fish",19);

Tip
One use for the second parameter is to search for multiple occurrences of a string. After finding the first occurrence, you search starting with that location for the second one, and so on.

A second method, lastIndexOf(), works the same way, but finds the last occurrence of the string. It searches the string backwards, starting with the last character. For example, this statement finds the last occurrence of "Fred" in the names string:

location = names.lastIndexOf("Fred");

As with indexOf(), you can specify a location to search from as the second parameter. In this case, the string will be searched backward starting at that location.

Changing a String's appearance

Several methods of the String object are available for displaying the string in various formats. These simply return a string consisting of the string enclosed by certain HTML tags. They do not modify the string itself. Here are the available attributes, and their equivalent HTML tags:

Tip
There are also two JavaScript functions, escape() and unescape(), which convert strings to URL encoding and back. These are explained in Chapter 17, "Combining JavaScript, CGI, and SSI."

Links and Anchors

The link() and anchor() methods of String objects can be used to produce HTML for links and anchors. The value of the string is used as the actual link or anchor value, and the parameter specifies the link to jump to or the anchor to set. For example, the following statement sets an anchor called "test" using the value "This is a Test":

"This is a Test".anchor("test");

and this statement sets a link on the words "Click Here" to the anchor defined previously:

"Click Here".link("#test");

Using Date Objects

The Date object is a built-in JavaScript object that enables you to conveniently work with dates and times. You can create a Date object any time you need to store a date, and use the Date object's methods to work with the date.

Strangely, the Date object has no properties. To set or obtain values from a Date object, you must use the methods described in the next section.

Note
JavaScript dates are stored as the number of milliseconds since January 1st, 1970, at midnight. This date is called the epoch. Dates before 1970 aren't allowed. This means I can't store my birthday in a Date object, and there's a good chance you can't either. Hopefully, this will be fixed in a future version of JavaScript. In the meantime, you can work with dates manually, using strings or numeric variables.

Creating a Date Object

You can create a Date object using the new keyword. You can also optionally specify the date to store in the object when you create it. You can use any of the following formats:

birthday = new Date();
birthday = new Date("June 20, 1996 08:00:00");
birthday = new Date(6, 20, 96);
birthday = new Date(6, 20, 96, 8, 0, 0);

You can choose any of these formats, depending on which values you wish to set.
If you use no parameters, as in the first example, the current date is stored in the object. You can then set the values using the set methods, described in the next section.

Setting Date Values

A variety of set methods enable you to set components of a Date object to values:

Getting Date Values

You can use the get methods to get values from a Date object. This is the only way to obtain these values, because they are not available as properties:

Working with Time Zones

A few functions are available to help you work with local time values and time zones:

Converting Between Date Formats

Two special methods of the Date object enable you to convert between date formats. These are not methods of individual Date objects; instead, you use them with the built-in object Date itself. These include the following:

The Math Object

The Math object is a bit different from the String and Date objects: it is a built-in object in itself, rather than an object class of which you can create instances. In other words, you can't create your own Math objects. The Math object exists automatically in any JavaScript program and encapsulates all of JavaScript's math capabilities.

The Math object's properties represent mathematical constants, and its methods are mathematical functions.

Note
Because you may use the Math object's properties and methods throughout an entire group of statements, you may find it useful to use the with keyword, introduced earlier in this chapter, to specify the Math object for those statements.

I will introduce some highlights of the Math object's methods in the following sections. For a complete list of the properties and methods of this object, including trigonometric and logarithmic functions, refer to appendix A.

Rounding and Truncating

Three of the most useful methods of the Math object enable you to round decimal values up and down:

All these take a single parameter: the number to be rounded. You might notice one thing missing: the ability to round to a decimal place, such as for dollar amounts. You can easily simulate this, though. Here's a function to round to two decimal places:

function round(num) {
   return Math.round(num * 100) / 100;

}

This function multiplies the value by 100 to move the decimal, then rounds the number to the nearest integer. Finally, the value is divided by 100 to restore the decimal. You'll use this function in an automatic order form in Chapter 6 "Using Interactive Forms."

Generating Random Numbers

One of the most commonly used methods of the Math object is the Math.random() method, which generates a random number. This method doesn't require any parameters. The number it returns is a random decimal number between 0 and 1.

You usually will want a random number between 1 and a value. You can do this with a general purpose random number function like this:

function rand(num) {
   return Math.floor(Math.random() * num) + 1;

}

This function multiplies a random number by the value you send it, then converts it to an integer between 1 and the number using the Math.floor() method.

The navigator Object

The navigator object is a special object that stores information about the version of the browser. This is a Netscape-specific tag, and it may or may not be implemented in other browsers. (This may make you question its usefulness.)

The navigator object doesn't technically qualify as a built-in object, because it represents a physical entity-the browser in use. In this way it's similar to the objects, such as window and document, which you will look at in Chapter 5. Because it isn't really part of the object hierarchy either, you'll examine it here.

The navigator object includes several properties that reflect information about the version of Netscape in use. These are all read-only properties:

Note
One use for the navigator object is to check for a particular version of Netscape; this is most useful if you are using a feature that was recently added and want to include an alternative for users of older versions.

There are also several properties of the navigator object that deal with Java, plug-ins, and multimedia documents:

Because these last two properties deal with plug-ins and multimedia, you'll take a closer look at them in Chapter 13, "Working with Multimedia and Plug-Ins." The navigator.javaEnabled property is described in detail in Chapter 16, "Integrating JavaScript with Java."

Customizing Objects

Along with the various built-in objects, you can also create objects of your own. You've already seen the basic example of doing this with the new keyword:

var = new ObjectType(parameters);

This assumes you have created an object definition for the object. Once you've done this, you can work with the properties and methods of the object, just like the built-in objects.

In object-oriented terms, the object definition defines a prototype for the object. This is the set of rules that govern how an object works. JavaScript provides a prototype keyword, which enables you to modify the prototype of all objects of a certain class.

As an example, suppose you defined an object called lunch with the following properties:

lunch.sandwich
lunch.drink
lunch.fruit

You could then create a lunch object like this:

mylunch = new lunch("bologna","coke","banana");

As you saw in other chapters, you could then add a property to the object:

mylunch.dessert = "pie";

With a prototype, though, you can add a property to the object definition itself. This command will add the dessert property to all existing and future lunch objects:

lunch.prototype.dessert = "cake";

Any lunch object created after this point will include this property, with a default value of "cake". The property will also be added to existing lunch objects. You can also extend the prototypes of the built-in objects, as you'll see in the next example.

Customizing the String Object

A powerful feature of the prototype keyword is the capability of extending the definitions of built-in objects. If you think the String object doesn't quite fit your needs, you can extend it, adding a new property or method.

As an example, let's add a method to the String object definition. There are a few methods, such as big(), blink(), and bold(), that output HTML tags with the string, but there is no method to work with headers. Listing 4.3 adds a head() method to the String object definition that will display the string as a heading.


Listing 4.3. Adding a method to the String object.
//define the function
function addhead (level) {
   html = "H" + level;
   text = this.toString();
   start = "<" + html + ">";
   stop = "</" + html + ">";
   return start + text + stop;
}
//add the method to the String prototype
String.prototype.head = addhead;
//test it
document.write ("This is a test".head(1));

First, you define the addhead() function, which will serve as the new string method. It accepts a number to specify the heading level. The start and stop variables are used to store the HTML begin and end header tags, such as <H1> and </H1>.

After the function is defined, you simply use the prototype keyword to add it as a method of the String object. You can then use this method on any String object; this is demonstrated by the last statement, which displays a quoted text string as a level-one header.

Workshop Wrap-Up

In this chapter, you learned the details of JavaScript's object-oriented capabilities, the various keywords used for working with objects in JavaScript, and techniques for working with objects and properties.

You also learned about the built-in objects that aren't directly related to Web pages:

Next Steps

You can now learn about the JavaScript object hierarchy and more advanced features:

Q&A

Q:
Do you really need to use objects within objects? Is there any practical reason to do this?
A:
JavaScript programs are usually simple, and you probably won't need data structures that are complicated very often. However, the object hierarchy--which you'll learn about in Chapter 5--uses these techniques heavily.
Q:
Most of the string appearance methods, such as string.big, take almost as much typing as simply including the appropriate HTML codes. Why would I use these?
A:
One reason is that they may be more readable if someone (including you) needs to read through the source code later. Another reason is that the HTML specification may change; presumably, future versions of JavaScript will use the appropriate codes for new versions of HTML, so you won't have to worry about updating your program.
Q:
Is there any limit to the length of a string variable in JavaScript?
A:
Strictly speaking, no. The only limitation is the memory available on the user's machine. You should keep lengths to a minimum, though, to avoid crashing the browser.