XML.com 
 Published on XML.com http://www.xml.com/pub/a/2006/06/07/object-oriented-javascript.html
See this if you're having trouble printing code examples

 

Object-oriented JavaScript
By Greg Brown
June 07, 2006

JavaScript is not generally considered a robust programming language, especially when compared to languages such as Java or C#: it is interpreted, rather than compiled; it is dynamically, rather than statically, typed; and it is commonly considered a procedural, rather than an object-oriented, language.

However, the demands on JavaScript as a development platform are growing with the increasing popularity of so-called AJAX applications. The procedural development model commonly used to add basic client-side interactivity to web pages today will not scale to support the level of UI complexity required by these applications. Fortunately, and contrary to popular belief, it is possible to apply object-oriented (OO) design principles in JavaScript, which can help manage this complexity. The next several sections explain how.

Encapsulation

In OO programming, a class is used to define a type of object that will be used by an application. The type encapsulates the data used by the object and may optionally expose methods to allow callers (other objects) to interact with the data.

Because JavaScript is not a statically typed language, it does not provide a keyword for defining a class or object-type definition. Additionally, because JavaScript is not compiled, there would be no way to enforce the proper use of such types. However, it is still possible to define custom objects in JavaScript that behave, in many ways, like classes in C# or Java.

For example, in a C# program, we might define a class to represent a family pet as follows:

// C# Pet class

public class Pet
{
    private string name;

    public Pet(string name)
    {
        this.name = name;
    }

    public string GetName()
    {
        return name;
    }
}

Our program might create an instance of the Pet class and invoke the GetName() method as follows:

Pet p = new Pet("Max");
System.Console.WriteLine(p.GetName());

In JavaScript, we would define the Pet class as follows:

// JavaScript Pet class

function Pet(name) {
    this._name = name;
}

Pet.prototype._name;

Pet.prototype.getName = function() {
    return this._name;
}

Our JavaScript program (most likely a web page) could create an instance of Pet and invoke the getName() method as follows:

var p = new Pet("Max");
alert(p.getName());

The result of running the above JavaScript code should be an alert that looks like this:

Figure 1
Figure 1. JavaScript alert

The following list compares the JavaScript version to the C# version:

Inheritance

Inheritance in object-oriented programming allows developers to define an "is a" relationship between classes. For example, we might want to extend our object model to define slightly more specialized versions of the Pet class: Dog and Cat. The base class, Pet, will contain any properties or methods shared by all Pets, but Dog and Cat may define additional properties or methods applicable only to instances of those classes. For example, our Dog class will provide a wag tail method, and the Cat class will provide a purr method.

In C#:

// C# Dog class

public class Dog : Pet
{
    public Dog(string name) : base(name)
    {
    }

    public void WagTail()
    {
        // Wagging
    }
}

// C# Cat class

public class Cat : Pet
{
    public Cat(string name) : base(name)
    {
    }

    public void Purr()
    {
        // Purring
    }
}

In JavaScript:

// JavaScript Dog class

function Dog(name) {
    Pet.call(this, name);
}

Dog.prototype = new Pet();

Dog.prototype.wagTail = function() {
    // Wagging
}

// JavaScript Cat class

function Cat(name) {
    Pet.call(this, name);
}

Cat.prototype = new Pet();

Cat.prototype.purr = function() {
    // Purring
}

Comparison:

We can use our new classes and methods as follows. (The only major difference is the declaration of the object types: in C#, Dog and Cat, and in JavaScript, var):

C#:

Dog d = new Dog("Max");
d.WagTail();

Cat c = new Cat("Fluffy");
c.Purr();

JavaScript:

var d = new Dog("Max");
d.wagTail();

var c = new Cat("Fluffy");
c.purr();

This program wouldn't generate any output. However, if we call the GetName()/getName() function from our earlier example, applying it to our Dog instance...

C#:

System.Console.WriteLine(d.GetName());

JavaScript:

alert(d.getName());

...the output is the same as when the method was called on the original Pet instance (see Figure 2):

Figure 2
Figure 2. The output is the same alert.

Polymorphism

Polymorphism refers to the ability of a caller to invoke a particular method or set of methods on an object without regard to the object's type. For example, we might want to add a speak() method to our Pet class, to allow our Pets to answer the phone when we are not at home; the caller on the other end of the line will not necessarily know or care which Pet is answering the phone, as long as it is able to speak():

In C#:

// C# Pet class

public class Pet
{
    // ...

    public virtual void Speak()
    {
        System.Console.WriteLine(GetName() + " says...");
    }
}

// C# Dog class

public class Dog : Pet
{
    // ...

    public override void Speak()
    {
        base.Speak();
        System.Console.WriteLine("woof");
    }
}

// C# Cat class

public class Cat : Pet
{
    // ...

    public override void Speak()
    {
        base.Speak();
        System.Console.WriteLine("meow");
    }
}

In JavaScript:

// JavaScript Pet class
// ...

Pet.prototype.speak = function() {
    alert(this.getName() + " says...");
}


// JavaScript Dog class
// ...

Dog.prototype.speak = function() {
    Pet.prototype.speak.call(this);
    alert("woof");
}


// JavaScript Cat class
// ...

Cat.prototype.speak = function() {
    Pet.prototype.speak.call(this);
    alert("meow");
}

Note that the same call() function used to invoke the base class constructor functions is also used to invoke method on the base class:

Pet.prototype.speak.call(this);

In this case, however, the target function name is the fully qualified name of the base class method, Pet.prototype.speak.

Invoking the methods is the same as before:

C#:

p = new Dog("Max");
p.Speak();

p = new Cat("Fluffy");
p.Speak();

JavaScript:

p = new Dog("Max");
p.speak();

p = new Cat("Fluffy");
p.speak();

The output of this program should be the following (see Figures 3-6):

Figure 3
Figure 3. Output is "Max says..."

Figure 4
Figure 4. Output is "woof"

Figure 5
Figure 5. Output is "Fluffy says..."

Figure 6
Figure 6. Output is "meow"

Although it may not offer features as powerful as C# or Java, JavaScript is more capable than many web developers may know, and it can be used to provide the structure of object-oriented development to the growing number of AJAX applications currently being deployed on the web.

XML.com Copyright © 1998-2006 O'Reilly Media, Inc.