Your Own Private Idaho()

 

Steven Disbrow is the owner of EGO Systems, a computer consulting firm in Chattanooga, TN. In the past, he has worked as a freelance programmer, Webmaster, editor, writer, and technical instructor. His most recent achievement was the creation of the Advance Shipping Notice Web site for the Tennessee Valley Authority. He can be contacted at [email protected].

ONE OF JAVASCRIPT'S greatest strengths, and one of its most overlooked features, is its object-oriented nature. While almost all JavaScript programmers make use of JavaScript's built-in objects (windows, forms, etc.), very few take the time to learn how to create JavaScript objects of their own. In fact, many programmers regard JavaScript as something of a "toy" language, unfit for serious programming.

Perhaps one reason for this is that JavaScript isn't truly object-oriented. At best, JavaScript can be called object-based. It has no inheritance or true user-defined classes, but it does implement rudimentary objects with instance variables and methods.

While this may sound like a rather uninspired object-oriented implementation, it's actually quite powerful and very well suited for the Web page environment. This month I show you how to create your own JavaScript objects for use on your Web pages. In future articles, I'll show you how to tie those objects to HTML controls to give your Web pages more functionality and flexibility.

PARTS OF A PROGRAMMER-CREATED JAVASCRIPT OBJECT
The JavaScript objects you create will have three parts:

  1. Constructor Function—This function will be called to create a new object of this type. This function must set up any instance variables and methods that the object will use.

  2. Instance Variables—As with other OOP languages, these are the variables that will be created for each instance of this type of object.

  3. Methods—As with other OOP languages, these are the functions that will be used by this type of object to work with its data.

Listing 1 shows a very simple programmer-created JavaScript object. In this example, the function "anObject()" is a constructor function that will be used with the "new" keyword to create objects of type "anObject." For example, the statements:
var myObject = 
new anObject();
var myOtherObject = new anObject();
will create two new variables of type "anObject." Both of these objects have an instance variable named "greeting" and they each have a method called "sayHello."

THE "THIS" KEYWORD
Inside our constructor function, you'll notice the "this" keyword. The "this" keyword simply refers to the object that is being created by the "new" keyword. The names that appear after the "this" keyword tell JavaScript what the names of our instance variables and methods should be. (Instance variable and method names are also sometimes referred to as slots.)

So, in our example, we are saying, "Inside this object that I am creating right now, I want two slots for instance variables and/or methods. The first slot will hold an instance variable called 'greeting.' And the second slot will be a method called 'sayHello'."

INSTANCE VARIABLES AND METHODS
What's the difference between defining an instance variable and a method? First, let's look at the line that defines our instance variable slot:

this.greeting = "Hi there!";
Notice that on this line, we are assigning a simple scalar value (a string) to the slot. By assigning a scalar or an object to a slot, you tell JavaScript that the slot is, in fact, an instance variable.

Methods are a bit more complicated. The last line of our constructor function creates a method for our object:

this.sayHello = doSayHello;
JavaScript knows that you want "sayHello" to be a method because "doSayHello" is not a simple scalar or an object, it's the name of a function that you will define elsewhere in your JavaScript code. This function (which does not have to have the same name as the method it's associated with) will implement the method that this line defines. In other words, when the "sayHello" method gets called, the "doSayHello" function is what actually gets executed.

That function is defined on the next few lines:

function doSayHello() {
	alert( this.greeting)
	}
Notice again the use of the "this" keyword. In this case, "this" refers to the object that actually invoked the function. So, the statement:
myObject.sayHello();
will call the "doSayHello" function. The "doSayHello" function will then display the instance variable "greeting" from "myObject."

METHODS AND PARAMETERS
Parameters are passed to methods in the standard way, but methods that accept parameters are defined in a slightly odd fashion. When you are defining a method that takes parameters, you do not list those parameters in the constructor function. Instead, you list them in the implementation function.

Listing 2 shows our simple object after changing it so that the "sayHello" method takes a parameter. Using this method definition, we must now pass a name string to the "sayHello" method when we invoke it. However, notice that the parameter information does not appear anywhere in our constructor function! Instead, the parameter information only appears in the implementation function for the method, the "doSayHello" function.

So, if we executed the following statements:

myObject = new anObject();
myObject.sayHello( "Steven");
An alert window would appear containing the string:
"Hi there! Nice to meet you Steven!"

DIFFERENCES FROM OTHER OBJECT-ORIENTED LANGUAGES
While the means of creating an object and its methods are slightly different from other OOP languages, the remainder of JavaScript's OOP implementation should be familiar. As we've already seen, methods and instance variables are referenced using simple dot-notation (i.e., objName.methodName(); or objName.variableName;).

Perhaps the biggest difference between JavaScript and other OOP languages is that JavaScript objects have no inheritance mechanism. This makes it rather difficult to reuse objects as the basis for new objects. About the best you can do is to include your old object in the definition of your new object as an instance variable. For example, if you wanted to create a new object "based" on our sample object, you might code a constructor function that looked like this:

function aNewObject() {
	this.baseObj = new anObject();
	this.var1 = 0;
	}
This will let you create a new object that has an instance of our old object inside of it. That object's instance variables and methods will then be available through standard dot notation. For example:
myNewObj = new aNewObject();
myNewObj.baseObj.sayHello("Steven");
HOW TO CREATE A STACK OBJECT IN JAVASCRIPT
One of the more common examples of JavaScript programming is how to create an Array object. So, I'm going to forgo that and give you a slightly more complex example of how to use what we've just looked at: how to create a stack in JavaScript.

A simple stack is one of the most useful objects to have in your programming toolbox. Like many languages, JavaScript doesn't have a built-in stack data type. Even worse, JavaScript doesn't support pointers of any kind. So, at first glance, adding a stack data type to JavaScript might appear difficult. However, if you can envision a stack in terms of objects sitting on top of one another, it's easy to add a stack object to JavaScript. But, instead of a single type of object, we'll need two: a stack element object and a stack object.

THE STACK ELEMENT OBJECT
Our stack will be made up of individual elements that we will "stack" on top of each other. Each of these individual elements is actually an object, the constructors for which are shown in Listing 3 (available at Java Report Online).

The instance variables and methods in the "oStackElement" object are straightforward:

  • data—This is the actual data that this stack element holds. This can be a simple scalar value or another object. (It could even be another stack object!)

  • next—This holds the next "oStackElement" object in our stack.

  • setData—This method sets the "data" instance variable for this "oStackElement" object.

  • getData—This method returns the "data" instance variable for this "oStackElement" object.

  • setNext—This method sets the "next" instance variable for this "oStackElement" object.

  • getNext—This method returns the "next" instance variable for this "oStackElement" object.
(The methods are very simple, so we won't look at them here. However, the source code is shown in Listing 3.)

THE STACK OBJECT
After we've defined what our stack elements look like we need to define our stack object. The code for this object, the "oStack" object, is also shown in Listing 3.

This is a simple object, with just two instance variables and three methods.

  • top—This instance variable will hold the object that sits at the top of our stack.

  • length—This instance variable tells us how many objects are in our stack.

  • isEmpty—This method tells us if the stack is empty.

  • push—This method pushes a new object onto the top of the stack.

  • pop—This method pulls the top object off of the stack and returns it.
The "isEmpty" method is very straightforward. It simply checks the "length" variable to see if it is zero. If it is, the stack is empty; otherwise, the stack is not empty.

The "push" and "pop" methods (shown in Listing 3) are a bit more interesting.

When we "push" an item onto our stack, the first thing we do is create a new "oStackElement" object to hold it. Then we place our data in this new object using the "setData" method. We then take the current top of the stack and assign it to the "next" field of the new item using the "setNext" method. Finally, we make our new item the top of the stack, and increment the "length" variable to show that our stack has increased in size by one element.

Popping an element off the stack is even simpler. All we need to do is capture the current top of the stack in a temporary variable and then reset the top to the next stack element (using the "getNext" method). After this is done, we decrement the "length" variable and return the former top element to the caller.

Note that when we return this top element, it's an "oStackElement" object! It's up to the caller to retrieve the data out of this object.

So, how do we use this object in a Web page? Listing 3 gives one answer. In this case, I've created a stack object and filled it with the names of my cats. I then retrieve the size of the stack and print out it's contents using a simple for loop and the "document.write()" method. Of course, you don't have to put cat names in the stack. Thanks to JavaScript's loose data typing, your stacks can contain strings, numbers, other objects, or whatever else you might want.

Quantity reprints of this article can be purchased by phone: 717.560.2001, ext.39 or by email: [email protected].