home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  


Previous Section Next Section

3.8 Creating a Custom Object

NN 3, IE 4

3.8.1 Problem

You want to create a custom object for your data structure.

3.8.2 Solution

As with creating arrays, object creation has both a long form and a compact form. The long form requires that you define a constructor function, while the compact form uses special inline symbols to denote the structure of the object.

A constructor function looks like any other JavaScript function, but its purpose is to define the initial structure of an object—it's property and method names—and perhaps to populate some or all of the properties with initial values. Values to be assigned to properties of the object are typically passed as parameters to the function, and statements in the function assign those values to properties. The following constructor function defines an object with two properties:

function coworker(name, age) {
    this.name = name;
    this.age = age;
}

To create objects with this constructor, invoke the function with the new keyword:

var emp1 = new coworker("Alice", 23);
var emp2 = new coworker("Fred", 32);

The this keyword in the constructor function localizes the context of the function to the object being created. As the function is reused for each object it creates, the context limits itself just to the one object under construction.

If you prefer not to use a constructor function, you can create objects with a shortcut syntax (Version 4 browsers or later) that defines an object inside curly braces. Property names and values are defined inside the curly braces as name/value pairs with a colon between the name and value, and each pair is comma-delimited. For example, the two objects just shown can be created using the shortcut syntax as follows:

var emp1 = {name:"Alice", age:23};
var emp2 = {name:"Fred", age:32};

After the objects are created, you access a property value just like you do with other JavaScript objects. For example, to display data from the emp2 object in an alert dialog box, the statement looks like the following:

alert("Employee " + emp2.name + " is " + emp2.age + " years old.");

After an object exists, you can add a new property to that instance by simply assigning a value to the property name of your choice. For example, to add a property about the cubicle number for Fred, the statement is:

emp2.cubeNum = 320;

After that assignment, only emp2 has that property (see Recipe 3.12 for more powerful assignments). There is no requirement that a property be predeclared in its constructor or shortcut creation code. This also means that you can be quite cavalier in your object creation to the point of generating a blank object and then populating it explicitly property by property:

var emp1 = new Object( );
emp1.name = "Alice";
emp1.age = 23;

This kind of object creation is usually more difficult to maintain in the source code and also takes up much more space if you need to create many similar objects.

3.8.3 Discussion

We've covered how to create properties for a custom object. Doing the same with methods is no more difficult. All it requires is that the method initially be defined in your source code as a JavaScript function; then assign a reference to that function as a value for a method name in either the constructor function or name/value pair inside curly braces. Continuing with the simple employee objects just shown, let's add a method to the object that displays an alert dialog box with the employee's name and age. Begin by defining the function that will do the work when invoked through one of the objects:

function showAll( ) {
    alert("Employee " + this.name + " is " + this.age + " years old.");    
}

Then assign the function to a method name in the constructor function:

function coworker(name, age) {
    this.name = name;
    this.age = age;
    this.show = showAll;
}

Or add the assignment to the shortcut constructors:

var emp1 = {name:"Alice", age:23, show:showAll};
var emp2 = {name:"Fred", age:32, show:showAll};

To invoke the method, do so via one of the objects:

emp1.show( );

Note how the context of the object passes through to the function when it is invoked as a method of the object. The this keywords in the function definition point back to the context of the object that invoked the method, and thus has immediate access to its companion properties.

JavaScript, as implemented in IE 4 and later or Navigator 4 and later, provides an extra shortcut operator in constructor functions that lets you automatically assign a default value to any property that has a null value passed to it in the function's parameter variables. For example, in the coworker object constructor function, if the statement that invokes the function leaves the second parameter blank, the age parameter variable is initialized as a null value. To provide a valid but harmless default value (of zero) to that property, the syntax is as follows:

function coworker(name, age) {
    this.name = name;
    this.age = age || 0;
    this.show = showAll;
}

The operator is the regular JavaScript OR operator. If the first value is null or undefined, the second value is assigned to the property. You can use this construction in any variable assignment in JavaScript.

One advantage to the longer constructor function approach is that you can include calls to other functions from inside the constructor. For example, you might wish to invoke some initialization routines with the object immediately as it is being created. Simply add the call to the function as another statement inside the constructor function. You can even pass a reference to the object under construction by passing this as a parameter. The following example builds on the coworker( ) constructor function previously shown. A separate function displays an alert dialog box each time an object is created:

function verify(obj) {
    alert("Just added " + obj.name + ".");
}
function coworker(name, age) {
    this.name = name;
    this.age = age;
    this.show = showAll;
    verify(this);
}

If the external function returns a value, the constructor function can assign that value to a property of the object.

If you are going to the trouble of creating a constructor function for a complex data structure, more than likely you are doing it for multiple instances of that object. But instead of having these objects floating around the window's scripting space as independent global variables, it will probably be more convenient to store these objects in an array of objects. As shown in Recipe 3.4, the array data structure facilitates iterating through a collection of similar items. For example, you could use an array of coworker objects to look through all records in search of those coworkers within a specific age range, and accumulate the names of those who meet your criteria.

Very little extra is needed to generate an array of objects while you are in the process of generating the objects themselves. The following demonstrates how a series of calls to a constructor function can be blended into an array constructor:

var employeeDB = new Array( );
employeeDB[employeeDB.length] = new coworker("Alice", 23);
employeeDB[employeeDB.length] = new coworker("Fred", 32);
employeeDB[employeeDB.length] = new coworker("Jean", 28);
employeeDB[employeeDB.length] = new coworker("Steve", 24);

You can do the same with shortcut syntax:

var employeeDB = new Array( );
employeeDB[employeeDB.length] = {name:"Alice", age:23, show:showAll};
employeeDB[employeeDB.length] = {name:"Fred", age:32, show:showAll};
employeeDB[employeeDB.length] = {name:"Jean", age:28, show:showAll};
employeeDB[employeeDB.length] = {name:"Steve", age:24, show:showAll};

Or you can go the whole route with shortcut syntax (albeit with one long statement):

var employeeDB = [{name:"Alice", age:23, show:showAll},
                  {name:"Fred", age:32, show:showAll},
                  {name:"Jean", age:28, show:showAll},
                  {name:"Steve", age:24, show:showAll}];

Finally, here's the function that looks for all coworkers in a certain age group:

function findInAgeGroup(low, high) {
    var result = new Array( );
    for (var i = 0; i < employeeDB.length; i++) {
        if (employeeDB[i].age >= low && employeeDB[i].age <= high) {
            result = result.concat(employeeDB[i].name);
        }
    }
    return result;
}

This function returns an array of the names of those whose ages fall between the low and high values passed as parameters.

As discussed in Recipe 3.9 and Recipe 3.11, an array of objects is one of the most flexible complex data structures available to JavaScript coders. During the design phase of your applications, look for opportunities to group together similar objects in arrays.

3.8.4 See Also

Recipe 3.9 for generating a fast hash table from an array of objects; Recipe 3.11 for sorting an array of objects based on object property values.

    Previous Section Next Section