Your Own Private Idaho()

By Steven Disbrow

08/22/2000

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 stevendisbrow@mindspring.com.

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:

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.

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

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:

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!)

(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:
sales@rmsreprints.com.