CONTENTS
Once you start to write more complex programs, you will quickly
find the need to perform some tasks and actions more than once
during the course of a program.
This need is addressed by functions, which are similar to methods
but are not attached to any particular object. As a programmer,
you can create numerous functions in your programs-this helps
organize the structure of your applications and makes maintaining
and changing your program code easier.
In addition, functions are particularly useful in working with
events and event handlers as you will learn in Chapter 5,
"Events in JavaScript."
You can also use functions as the basis for creating your own
objects to supplement those available to you in JavaScript.
In this chapter we will cover these topics:
- The nature of functions
- Built-in functions versus programmer-created functions
- How to define and use functions
- How to create new objects, properties, and methods
- How to use associative arrays
Functions offer the ability for programmers to group together
program code that performs a specific task-or function-into a
single unit that can be used repeatedly throughout a program.
Like the methods you have seen in earlier chapters, a function
is defined by name and is invoked by using its name.
Also, like some of the methods you have seen before (such as prompt()
and confirm()), functions
can accept information in the form of arguments and can return
results.
JavaScript includes several built-in functions as well as methods
of base objects. You have already seen these when you used alert(),
document.write(), parseInt(),
or any of the other methods and functions you have been working
with. The flexibility of JavaScript, though, lies in the ability
for programmers to create their own functions to supplement those
available in the JavaScript specification.
In order to make use of functions, you need to know how to define
them, pass arguments to them, and return the results of their
calculations. It is also important to understand the concept of
variable scope, which governs whether a variable is available
in an entire script or just within a specific function.
Functions are defined using the function
statement. The function statement
requires a name for the function, a list of parameters-or arguments-that
will be passed to the function, and a command block that defines
what the function does:
function function_name(parameters,
arguments) {
command block
}
As you will notice, the naming of functions follows basically
the same rules as variables: They are case sensitive, can include
underscores (_), and start with a letter. The list of arguments
passed to the function appears in parentheses and is separated
by commas.
It is important to realize that defining a function does not execute
the commands that make up the function. It is only when the function
is called by name somewhere else in the script that the function
is executed.
In the following function, you can see that printName()
accepts one argument called name:
function printName(name) {
document.write("<HR>Your Name is <B><I>");
document.write(name);
document.write("</B></I><HR>");
}
Within the function, references to name
refer to the value passed to the function.
There are several points here to note:
- Both variables and literals can be passed as arguments when
calling a function.
- If a variable is passed to the function, changing the value
of the parameter within the function does not change the value
of the variable passed to the function.
- Parameters exist only for the life of the function-if you
call the function several times, the parameters are created afresh
each time you call the function, and values they held when the
function last ended are not retained.
For example, if you call printName()
with the command:
printName("Bob");
then, when printName() executes,
the value of name is "Bob".
If you call printName() by
using a variable for an argument:
var user = "John";
printName(user);
then name has the value "John".
If you were to add a line to printName()
changing the value of name:
name = "Mr. " + name;
name would change, but the variable user,
which was sent as an argument, would not change.
Note |
When passing arguments to a function, two properties that can be useful in working with the arguments are created: functionname.arguments and function.arguments.length. functionname.arguments is an array with an entry for each
argument and functionname.argument.length is an integer variable indicating the number of variables passed to the function. You can use these properties to produce functions that accept a variable number of arguments.
|
Variable Scope
This leads to a discussion of variable scope. Variable scope refers
to where a variable exists.
For instance, in the example printName(),
name exists only within the
function printName()-it cannot
be referred to or manipulated outside the function. It comes into
existence when the function is called and ceases to exist when
the function ends. If the function is called again, a new instance
of name is created.
In addition, any variable declared using the var
command within the function will have a scope limited to the function.
If a variable is declared outside the body of a function, it is
available throughout a script-inside all functions and elsewhere.
 |
Variables declared within a function are known as local variables. Variables declared outside functions and available throughout the script are known as global variables.
|
If you declare a local variable inside a function that has the
same name as an existing global variable, then inside the
function, that variable name refers to the new local variable
and not the global variable. If you change the value of
the variable inside the function, it does not affect the value
of the global variable.
As mentioned in the previous section, functions can return results.
Results are returned using the return
statement. The return statement
can be used to return any valid expression that evaluates to a
single value. For example, in the function cube(),
function cube(number) {
var cube = number * number * number;
return cube;
}
the return statement will
return the value of the variable cube.
This function could just as easily have been written like this:
function cube(number) {
return number * number * number;
}
This works because the expression number
* number * number evaluates to a single value.
As was mentioned in Chapter 3, "Working
with Data and Information," there are compelling reasons
to include function definitions inside the HEAD
tags of the HTML file.
This ensures that all functions have been parsed
before it is possible for user events to invoke a function. This
is especially relevant once you begin working with event handlers
where incorrect placement of a function definition can mean an
event can lead to a function call when the function has not been
evaluated and Navigator doesn't know it exists. When this happens,
it causes an error message to be displayed.
 |
The term parsed refers to the process by which the JavaScript interpreter evaluates each line of script code and converts it into a pseudo-compiled Byte Code (much like Java), before attempting to execute it. At this time, syntax errors and other
programming mistakes that would prevent the script from running may be caught and reported to the user or programmer.
|
JavaScript offers an operator that we didn't discuss in the last
chapter when we looked at variables, expressions, and operators.
The typeof operator is used
to identify the type of an element in JavaScript. Given an unevaluated
operand (such as a variable name or a function name), the typeof
operator returns a string identifying the type of the operand.
For instance, suppose you have the following JavaScript code:
var question="What is 10 x 10?";
var answer=10;
var correct=false;
function showResult(results) {
document.write(results);
}
Then, typeof question returns
string; typeof
answer returns number;
typeof correct re-turns boolean;
and typeof showResult returns
function. Other possible
results returned by the typeof
operator include undefined
and object.
Note |
The typeof operator can be useful in determining if a function has been loaded and is ready to be called. This is especially useful in multi-frame pages where a script loaded in one frame might be trying to call a function located in another frame
that hasn't completed loading.
|
Frames are covered in more detail in Chapter 8.
To demonstrate the use of functions, you are going to rewrite
the simple test question example you used in Listing 3.3. In order
to do this, you are going to create a function that receives a
question as an argument, poses the question, checks the answer,
and returns an output string based on the accuracy of the user's
response as shown in Listing 4.1
In order to do this, you need to learn the eval()
method, which evaluates a string to a numeric value; for instance,
eval("10*10")
returns a numeric value of 100.
Listing 4.1. Evaluating an expression with the eval()
function.
<HTML>
<HEAD>
<TITLE>Example 4.1</TITLE>
<SCRIPT LANGUAGE="JavaScript">
<!-- HIDE FROM OTHER BROWSERS
//DEFINE FUncTION testQuestion()
function testQuestion(question) {
//DEFINE LOCAL VARIABLES FOR THE FUncTION
var answer=eval(question);
var output="What is " + question + "?";
var correct='<IMG SRC="correct.gif">';
var incorrect='<IMG SRC="incorrect.gif">';
//ASK THE QUESTION
var response=prompt(output,"0");
//chECK THE RESULT
return (response == answer) ? correct : incorrect;
}
// STOP HIDING FROM OTHER BROWSERS -->
</SCRIPT>
</HEAD<
<BODY>
<SCRIPT LANGUAGE="JavaScript">
<!-- HIDE FROM OTHER BROWSERS
//ASK QUESTION AND OUTPUT RESULTS
var result=testQuestion("10 + 10");
document.write(result);
//STOP HIDING FROM OTHER BROWSERS -->
</SCRIPT>
</BODY>
</HTML>
 |
At first glance, this script may seem a little more complicated than the version used in Listing 3.3. In reality, though, it simply separates the work into logical blocks and moves most of the work into the function testQuestion().
|
To understand the function, let's analyze the key lines.
function testQuestion(question) {
In this line, you define the function testQuestion()
and indicate that it receives one argument, which is referred
to as question within the
function. In the case of this function, it is expected that question
will be a string containing an arithmetic expression.
var answer=eval(question);
The first thing you do after entering the function is to declare
the variable answer and assign
to it the numeric value of the arithmetic expression contained
in the string question. This
is achieved using the eval()
function.
var output="What is
" + question + "?";
var correct='<IMG SRC="correct.gif">';
var incorrect='<IMG SRC="incorrect.gif">';
In these lines you declare several more variables. The variable
output contains the actual
question to display, which is created using the concatenation
operator.
var response=prompt(output,"0");
Here you ask the question and assign the user's response to the
variable response.
return (response == answer) ? correct
: incorrect;
In this line you use the conditional operator to check the user's
response. The resulting value is returned by the return
command.
Now that you understand the function, it should be clear how you
are invoking it later in the body of the HTML file. The line
var result=testQuestion("10 + 10");
calls testQuestion() and
passes a string to it containing an arithmetic expression. The
function returns a result, which is stored in the variable result.
Then you are able to output the result using document.write().
These two lines could be condensed into a single line:
document.write(testQuestion("10
+ 10"));
Now that you have seen an example of how functions work, let's
take a look at an application of functions called recursion.
 |
Recursion refers to situations in which functions call themselves. These types of functions are known as recursive functions.
|
For instance, the following is an example of a recursive function
that calculates a factorial:
Note |
A factorial is a mathematical function. For example, factorial 5 (written 5!) is equal to 5×4×3×2×1 and 7! = 7×6×5×4×3×2×1.
|
function factorial(number) {
if (number > 1) {
return number * factorial(number - 1);
} else {
return number;
}
}
At first glance, this function may seem strange. This function
relies on the fact that the factorial of a number is equal to
the number multiplied by the factorial of one less than the number.
Expressed mathematically, this could be written:
x! = x * (x-1)!
In order to apply this formula, you have created a recursive function
called factorial(). The function
receives a number as an argument. Using the following if-else
construct:
if (number > 1) {
return number * factorial(number - 1);
} else {
return number;
}
The function either returns a value of 1
if the argument is equal to 1
or applies the formula and returns the number multiplied by the
factorial of one less than the number.
In order to do this, it must call the function factorial()
from within the function factorial().
This is where the concept of variable scope becomes extremely
important. It is important to realize that when the function calls
factorial(), a new instance
of the function is being invoked, which means that a new instance
of number is created. This
continues to occur until the expression number-1
has a value of 1.
Tip |
Recursive functions are powerful, but they can be dangerous if you don't watch out for infinite recursion. Infinite recursion occurs when the function is designed in such a way as to call itself forever without stopping.
At a practical level, in JavaScript, infinite recursion isn't likely to happen because of the way in which JavaScript handles some of its memory allocation. This means that deep recursions, even if they aren't infinite, may cause Navigator to
crash.
|
It is important to note that the function factorial()
prevents infinite recursion because the if-else
construct ensures that eventually the function will stop calling
itself once the number passed to it is equal to one. In addition,
if the function is initially called with a value less than two,
the function will immediately return without any recursion.
Using recursive functions, it is possible to extend the program
used in Listing 4.1 so that it continues to ask the question until
the user provides the correct answer, as shown in
Listing 4.2.
Listing 4.2. Using a recursive function to repeat input.
<HTML>
<HEAD>
<TITLE>Example 4.2</TITLE>
<SCRIPT LANGUAGE="JavaScript">
<!-- HIDE FROM OTHER BROWSERS
//DEFINE FUncTION testQuestion()
function testQuestion(question) {
//DEFINE LOCAL VARIABLES FOR THE FUncTION
var answer=eval(question);
var output="What is " + question + "?";
var correct='<IMG SRC="correct.gif">';
var incorrect='<IMG SRC="incorrect.gif">';
//ASK THE QUESTION
var response=prompt(output,"0");
//chECK THE RESULT
return (response == answer) ? correct : testQuestion(question);
}
// STOP HIDING FROM OTHER BROWSERS -->
</SCRIPT>
</HEAD<
<BODY>
<SCRIPT LANGUAGE="JavaScript">
<!-- HIDE FROM OTHER BROWSERS
//ASK QUESTION AND OUTPUT RESULTS
var result=testQuestion("10 + 10");
document.write(result);
//STOP HIDING FROM OTHER BROWSERS -->
</SCRIPT>
</BODY>
</HTML>
 |
Notice that you have made only a single change to the conditional expression:
|
return (response == answer) ? correct
: testQuestion(question);
Where you originally returned the value of the variable incorrect
when the user provided an incorrect response, you are now returning
the result of asking the question again (by calling testQuestion()
again).
It is important to realize that this example could cause JavaScript
to crash because of its memory handling problems if the user never
provides the correct answer. This can be remedied by adding a
counter to keep track of the number of chances the user has to
provide a correct answer:
<HTML>
<HEAD>
<TITLE>Example 4.2</TITLE>
<SCRIPT LANGUAGE="JavaScript">
<!-- HIDE FROM OTHER BROWSERS
//DEFINE FUncTION testQuestion()
function testQuestion(question,chances) {
//DEFINE LOCAL VARIABLES FOR THE FUncTION
var answer=eval(question);
var output="What is " + question + "?";
var correct='<IMG SRC="correct.gif">';
var incorrect='<IMG SRC="incorrect.gif">';
//ASK THE QUESTION
var response=prompt(output,"0");
//chECK THE RESULT
if (chances > 1) {
return (response == answer) ? correct
: testQuestion(question,chances-1);
} else {
return (response == answer) ? correct
: incorrect;
}
}
// STOP HIDING FROM OTHER BROWSERS -->
</SCRIPT>
</HEAD<
<BODY>
<SCRIPT LANGUAGE="JavaScript">
<!-- HIDE FROM OTHER BROWSERS
//ASK QUESTION AND OUTPUT RESULTS
var result=testQuestion("10 + 10",3);
document.write(result);
//STOP HIDING FROM OTHER BROWSERS -->
</SCRIPT>
</BODY>
</HTML>
By adding the if-else construct
when you check the user's answer, you are ensuring that you cannot
enter an infinite recursion. The if-else
construct could be replaced by a conditional expression:
return (response == answer) ? correct
: ((chances > 1) ?
testQuestion(question,chances-1)
: incorrect);
What this expression says is, if the user's response is correct
(response==answer evaluates
to true), then return the
value of correct. Otherwise,
if there are chances left (chances >
1 evaluates to true),
ask the question again and return the result. If there are no
chances left and the answer is incorrect, return the value of
the variable incorrect.
As you learned earlier, it is possible to use functions to build
custom objects in JavaScript. In order to do this, you must be
able to define an object's properties, to create new instances
of objects, and to add methods to objects.
Before creating a new object, it is necessary to define that object
by outlining its properties. This is done by using a function
that defines the name and properties of the function.
 |
This type of function is known as a constructor function.
|
If you want to create an object type for students in a class,
you could create an object named student
with properties for name,
age, and grade.
This could be done with the function:
function student(name,age, grade) {
this.name = name;
this.age = age;
this.grade = grade;
}
Note |
Notice the use of the special keyword this. this plays a special role in JavaScript and refers to the current object. You will learn more about this in Chapter 5, when we begin discussing event handlers.
|
Using this function, it is now possible to create an object using
the new statement:
student1 = new student("Bob",10,75);
This line of JavaScript code creates an object called student1
with three properties: student1.name,
student1.age, and student1.grade.
This is known as an instance of the object student.
By creating a new object student2
using the new statement,
student2 = new student("Jane",9,82);
you would be creating a new instance of the object that is independent
from student1.
It is also possible to add properties to objects once they are
created simply by assigning values to a new property. For instance,
if you want to add a property containing Bob's mother's name,
you could use the structure
student1.mother = "Susan";
This would add the property to student1
but would have no effect on student2
or future instances of the student
object. To add the property mother
to all instances of student,
it would be necessary to add the property to the object definition
before creating instances of the object:
function student(name, age, grade, mother)
{
this.name = name;
this.age = age;
this.grade = grade;
this.mother = mother;
}
You can also use objects as properties of other objects. For instance,
if you were to create an object called grade
function grade (math, english, science)
{
this.math = math;
this.english = english;
this.science = science;
}
you could then create two instances of the grade
object for the two students:
bobGrade = new grade(75,80,77);
janeGrade = new grade(82,88,75);
Note |
The order of arguments is important in JavaScript. In the preceding example, if Jane hasn't taken English, you would need to pass a place-holder to the function, such as zero or a string value, such as "N/A" or the empty string. The
function would then need to be written to handle this eventuality.
|
Using these objects, you could then create the student objects
like this:
student1 = new student("Bob",10,bobGrade);
student2 = new student("Jane",9,janeGrade);
You could then refer to Bob's math grade as student1.grade.math
or Jane's science grade as student2.grade.science.
In addition to adding properties to object definitions, you can
also add a method to an object definition. Because methods are
essentially functions associated with an object, first you need
to create a function that defines the method you want to add to
your object definition.
For instance, if you want to add a method to the student
object to print the student's name, age, and grades to the document
window, you could create a function called displayProfile():
function displayProfile() {
document.write("Name: " + this.name + "<BR>");
document.write("Age: " + this.age + "<BR>");
document.write("Mother's Name: " + this.mother
+ "<BR>");
document.write("Math Grade: " + this.grade.math
+ "<BR>");
document.write("English Grade: " + this.grade.english
+ "<BR>");
document.write("Science Grade: " + this.grade.science
+ "<BR>");
}
Note |
Here again, you use this to refer to the object that is invoking the method. If you call a method as object1.method, then this refers to object1.
|
Having defined the method, you now need to change the object definition
to include the method:
function student(name,age, grade) {
this.name = name;
this.age = age;
this.grade = grade;
this.mother = mother;
this.displayProfile = displayProfile;
}
Then, you could output Bob's student profile by using the command:
student1.displayProfile();
Starting with Navigator 3.0, it is possible to extend objects
after they have been created with a new
statement.
Properties can be added to object definitions by setting the value
of objectName.prototype.propertyName.
objectName refers to the
name of the constructor function, and propertyName
is the name of the property or method being added to the function.
For instance, if you want to add an additional method called updateProfile()
to the student object definition
you created earlier, you could use the command:
student.prototype.updateProfile = updateInfo;
where you have already created a function called updateInfo():
function updateInfo() {
this.age = prompt("Enter the correct age
for " + this.name,this.age);
this.mother = prompt("Enter the mother's
name for " + this.name,this.mother);
}
Then, all instances of student
that had previously been created using the new
statement would be able to use the new method.
In the example we used above, you could update the age and mother's
name for Bob by using this command:
student1.updateProfile();
To further demonstrate the application of objects and defining
your own objects, Listing 4.3 is a program that asks the user
for personnel information of an employee and then formats it for
display on the screen.
In order to do this, you need to define an employee
object, as well as a method for displaying the employee information.
Listing 4.3. Creating an employee profile.
<HTML>
<HEAD>
<TITLE>Example 4.3</TITLE>
<SCRIPT LANGUAGE="JavaScript">
<!-- HIDE FROM OTHER BROWSERS
//DEFINE METHOD
function displayInfo() {
document.write("<H1>Employee Profile: "
+ this.name + "</H1><HR><PRE>");
document.writeln("Employee Number: " + this.number);
document.writeln("Social Security Number: "
+ this.socsec);
document.writeln("Annual Salary: " + this.salary);
document.write("</PRE>");
}
//DEFINE OBJECT
function employee() {
this.name=prompt("Enter Employee's Name","Name");
this.number=prompt("Enter Employee Number for
" + this.name,"000-000");
this.socsec=prompt("Enter Social Security Number
for " +
this.name,"000-00-0000");
this.salary=prompt("Enter Annual Salary for "
+ this.name,"$00,000");
this.displayInfo=displayInfo;
}
newEmployee=new employee();
// STOP HIDING FROM OTHER BROWSERS -->
</SCRIPT>
</HEAD>
<BODY>
<SCRIPT LANGUAGE="JavaScript">
<!-- HIDE FROM OTHER BROWSERS
newEmployee.displayInfo();
// STOP HIDING FROM OTHER BROWSERS -->
</SCRIPT>
</BODY>
</HTML>
This script produces results similar to those in Figure 4.2 and
4.3.
Figure 4.2 :The program prompts the user for the employee information.
Figure 4.3 : The method you defined displays the formatted data.
 |
In this example, the most noticeable variation on what you have learned is that you don't pass any arguments to the object definition function, employee().
|
Instead, this object definition is more of a dynamic object definition
in that, when a new instance of the object is created, the user
is prompted for all the relevant data for the properties.
In Navigator 2.0, it was possible to refer to object properties
numerically in two ways other than objectName.propertyName.
That is, in the previous example of the student
object, the properties of student2
could have been referred to as:
student2["name"]
student2["age"]
and so on, or by numbers starting at zero, where
student2[0] == "Jane"
student2[1] == 9
 |
This use of the names and numbers is known as indexes.
|
In Navigator 3.0, it is no longer possible to refer to a property
both by numeric index and by name. Instead, properties can either
be created as numeric indexes or names but then
all subsequent references have to be the same. Numbers and names
cannot be used inter-changeably.
Anyone who has programmed in other structured languages has probably
encountered arrays of one sort or another and will be wondering
where JavaScript's arrays are.
Arrays are ordered collections of values referred to by a single
variable name. For instance, if you have an array named student,
you might have the following ordered values:
student[0] = "Bob"
student[1] = 10
student[2] = 75
Array elements are referred to by their indexes-the numbers in
brackets. In JavaScript, arrays start with index zero.
Arrays in JavaScript are created using the Array()
constructor object. You can create an array of undefined length
by using the r">new keyword:
arrayName = new Array();
The length of the array changes dynamically as you assign values
to the array. The length of the array is defined by the largest
index number used.
For instance
var sampleArray = new Array();
sampleArray[49] = "50th Element";
creates an array with 50 elements. (Remember, indexes start at
zero.)
It is also possible to define an initial length of an array by
passing the length to the Array()
object as an argument:
var sampleArray = new Array(100);
In addition, you can create an array and assign values to all
its elements at the time it is defined. This is done by passing
the value for all elements as arguments to the Array()
object. For instance,
var sampleArray = new Array("1st
Element", 2, "3rd Element);
creates a three-element array with the values
sampleArray[0] == "1st Element"
sampleArray[1] == 2
sampleArray[2] == "3rd Element"
As objects, arrays have several methods, including
- join() returns all elements
of the array joined together as a single string. This takes one
argument: a string used as the separator between each element
of the array in the final string. If the argument is omitted,
join() uses a comma-space
as the separator.
- reverse() reverses the
order of elements in the array.
To demonstrate how arrays can be useful, Listing 4.4 builds on
the personnel information example in the Listing 4.3.
In this example, you do not have the user enter the personnel
information for the new employee in the same way. You present
a list of information you want. The users select a number for
the information they want to enter. When they are done, they select
"0."
After a user finishes entering the information, the script displays
the formatted employee profile.
Listing 4.4. Creating a user menu.
<HTML>
<HEAD>
<TITLE>Listing 4.4</TITLE>
<SCRIPT LANGUAGE="JavaScript">
<!-- HIDE FROM OTHER BROWSERS
//DEFINE METHOD
function displayInfo() {
document.write("<H1>Employee Profile: "
+ this.data[0] + "</H1><HR><PRE>");
document.writeln("Employee Number: " + this.data[1]);
document.writeln("Social Security Number: "
+ this.data[2]);
document.writeln("Annual Salary: " + this.data[3]);
document.write("</PRE>");
}
//DEFINE METHOD TO GET EMPLOYEE INFORMATION
function getInfo() {
var menu="0-Exit/1-Name/2-Emp. #/3-Soc. Sec.
#/4-Salary";
var choice=prompt(menu,"0");
if (choice != null) {
if ((choice < 0) || (choice > 4))
{
alert ("Invalid choice");
this.getInfo();
} else {
if (choice != "0")
{
this.data[choice-1]=prompt("Enter
information","");
this.getInfo();
}
}
}
}
//DEFINE OBJECT
function employee() {
this.data = new Array(4);
this.displayInfo=displayInfo;
this.getInfo=getInfo;
}
newEmployee=new employee();
// STOP HIDING FROM OTHER BROWSERS -->
</SCRIPT>
</HEAD>
<BODY>
<SCRIPT LANGUAGE="JavaScript">
<!-- HIDE FROM OTHER BROWSERS
newEmployee.getInfo();
newEmployee.displayInfo();
// STOP HIDING FROM OTHER BROWSERS -->
</SCRIPT>
</BODY>
</HTML>
 |
In this example, you can see several of the concepts you have learned in action here, including recursion and arrays.
|
The method getInfo() needs
some explanation:
var menu="0-Exit/1-Name/2-Emp. #/3-Soc.
Sec. #/4-Salary";
The menu variable contains
the string that presents the choices to the user. Notice the use
of the \n special character
to create a multiline menu in a single text string.
var choice = prompt(menu,"0");
Here you present the menu to the user and ask for a choice, which
is stored in the variable choice.
if (choice != null) {
if ((choice < 0) || (choice > 4))
{
alert ("Invalid choice");
this.getInfo();
} else {
if (choice != "0")
{
this.data.[choice-1]=prompt("Enter
information","");
this.getInfo();
}
}
}
This set of if statements
is where the real work of the getInfo()
method is done. The first if
statement checks whether the user has selected Cancel. If not,
then the user's choice is checked to make sure it is in range
(from zero to four). If the choice is out of range, then the user
is alerted, and the getInfo()
method is called again. If the user's choice is in range, it is
checked to see if the user has chosen 0
for exit. If the user doesn't select 0,
the user is prompted to enter the data he has indicated. Then
the getInfo() method is called
again to present the menu again.
You will notice the use of the this
keyword to refer to the current object and the use of this
data [choice-1] to refer to the array element (or
property) selected by the user. You use choice-1
because the menu presents choices from 1
to 4 to the user, but array
indexes start from 0 and,
in this case, the index goes up to 3.
Functions in JavaScript can be created as instances of the special
Function object using the
new keyword:
functionName = new Function(arglist,
functionDefinition);
This provides an alternate way to create functions. In the example
above, arglist is a comma-separated
list of argument names, and functionDefinition
is the JavaScript code to be executed each time the function is
called. Each item in the argument list should be a string literal.
Functions defined using the Function
object can be used in the same way as functions defined using
the function keyword (including
in event handlers) and can be called directly in expressions.
Instances of the Function
object have two properties:
- arguments An
array corresponding to the arguments of the function in the order
they are defined.
- prototype As
you learned earlier in this chapter, prototype
can be used to add properties and methods to objects.
According to the Netscape documentation, creating functions using
the Function object is the
less efficient of the two methods of creating objects.
Functions provide a means to define segments of code that can
be used more than once in a program. Like methods, which are part
of objects, functions are defined by names, can be passed arguments,
and can return results.
Variable scope, whether a variable exists locally to a function
or globally for the entire program, is an important concept in
dealing with functions.
Recursive functions are functions that call themselves one or
more times. Recursion is a powerful tool, but it needs to be used
carefully to avoid infinite recursion, which occurs when a function
repeatedly calls itself without ever ending. With the current
implementation of JavaScript, infinite recursion can't really
happen because memory handling shortcomings mean that Navigator
will crash when recursion gets too deep.
Functions are also used to define the properties and objects that
make up user-defined methods. Using the new
keyword, it is possible to create multiple instances of an object
which all exist independently.
Arrays provide a mechanism to group together data into ordered
collections. Index numbers provide a means to access individual
elements in an array.
If you have made it to the end of this chapter, you are making
progress because recursion, functions, and objects are advanced
topics.
In Chapter 5, you begin to work with events
and event handlers which will allow you to design programs that
interact with the user in a sophisticated way.
Command/Extension | Type
| Description |
function
| JavaScript keyword | Declares a function
|
new |
JavaScript keyword | Creates a new instance of an object
|
eval()
| JavaScript method | Evaluates a string to a numeric value
|
this |
JavaScript keyword | Refers to the current object
|
type of
| JavaScript operator | Returns a string indicating the type of the operand
|
- Write the object definition for an object called car
with four properties: model,
make, year,
and price.
- If you have an object defined as follows
function house(address,rooms,owner) {
this.address = address;
this.rooms = rooms;
this.owner = owner;
}
and you create two instances of the house
object
house1 = new house("10 Maple St.",10,"John");
house2 = new house("15 Sugar Rd.",12,"Mary");
then, what would be the value of the following:
a. house1.rooms
b. house2.owner
c. house1["address"]
- Create a function that calculates the value of x
to the power of y. For instance,
if you have a function called power()
and you issue the command
value = power(10,4);
then power()
should return the value of 10
to the power of 4, or 10
* 10 * 10 * 10.
Note |
If the notation x^y refers to x to the power of y, then it will be helpful in writing this function to realize that x^y = x * x^(y-1).
|
- The object definition would look like this:
function car(model, make, year, price)
{
this.model = model;
this.make = make;
this.year = year;
this.price = price;
}
- The values are as follows:
a. 10
b. "Mary"
c. "10 Maple
St."
- The power() function
could be written using recursion:
function power(number, exponent) {
if (exponent > 1) {
return number * power(number, exponent
- 1);
} else {
return 1;
}
}
This function makes use of a similar principle as
the factorial example earlier in the chapter. This function uses
the fact that x to the power
of y equals x
multiplied by x to the power
of y-1.
While this function works, it is important to note that it isn't
perfect. Although negative exponents are mathematically legal,
this function will not calculate the result correctly for this
type of exponent.
Remembering that x to the
power of -y is the same as
1 divided by x to the power
of y, you could fix the problem
with negative exponents by making the following change to the
function:
function power(number, exponent) {
// chECK IF WE HAVE A NEGATIVE EXPONENT
var negative = (exponent < 0) ? true : false;
// DECLARE WORKING VARIABLE
var value=0;
// CALCULATE number TO THE POWER OF exponent
if (exponent > 1) {
value = number * power(number, exponent
- 1);
} else {
value = 1;
}
// IF THE EXPONENT WAS NEGATIVE, TAKE THE RECIPROCAL
if (negative)
value = 1 / value;
return value;
}