PART I JAVAWHAT? THE WHERE, WHY, AND HOW OF JAVASCRIPT
Chapter 9 The Browser Object Model 151
Working with functions
After reading this chapter, you’ll be able to
■
■ Understand the purpose of functions in JavaScript.
■
■ Define your own functions.
■
■ Call functions and receive data back from them.
■
■ Understand some of the built-in functions in JavaScript.
What’s in a function?
A JavaScript function is a collection of statements, either named or unnamed (anonymous), that can be called from elsewhere within a JavaScript program. Functions can accept arguments, which are input values passed into the function. Within a function, those arguments passed into the function can be acted upon and the results returned to the caller of the function via a return value.
Functions are perfect when you have something that needs to happen multiple times within a pro- gram. Rather than defining the same code multiple times, you can use a function (which is really just like a mini-program inside a program) to perform that action. Even if you have bits of code that are very similar—but not identical—throughout the program, you might be able to abstract them into a single function.
A good example of abstracting similar code is using a function to verify that required form fields have been filled in. You could write JavaScript code to verify each individual named field in the form, or you could use a function.
You’ve already seen functions at work through examples in earlier chapters. A function is defined with the keyword function, usually followed by the name of the function, and then by parentheses
Tip It’s important to note that when a function is defined (you can see this in the preced- ing basic function definition), the code isn’t actually executed until the function is invoked, or called. You see how to call a function later in this chapter.
Function parameters
Place parameters passed to a function within the parentheses of the function definition. Here’s a brief example of using function arguments:
function myFunction(parameter1, parameter2, ..., parameterN) {
}
Here's an example with two parameters:
function myFunction(parameter1, parameter2) { // Do something
}
Calling, or invoking, the function is as simple as:
myFunction(val1,val2);
One of the differences between JavaScript (the ECMA-262 specification) and other languages is that in JavaScript you don’t need to specify the number of parameters or arguments being passed into a function, and the number of arguments being passed in does not need to match those that are defined in the function definition. When invoked, the function is given an array object named argu- ments. The arguments object holds the arguments sent into the function, which can be helpful when you don’t know the number of arguments being sent in. Here’s an example of how this is done:
function myFunction() {
var firstArg = arguments[0];
var secondArg = arguments[1];
}
Better still, you could get the length of the arguments object and loop through each argument, as follows (also in the functionbasics.txt file in the companion content):
function myFunction() {
var argLength = arguments.length;
for (var i = 0; i < argLength; i++) { // Do something with each argument (i) }
}
Here’s a more complete example showing the results from a simple use of the arguments object:
<!doctype html>
<html>
<head>
<title>Arguments Array</title>
</head>
<body>
<script type="text/javascript">
function myFunction() {
var firstArg = arguments[0];
var secondArg = arguments[1];
alert("firstArg is: " + firstArg);
alert("secondArg is: " + secondArg);
}
myFunction("hello","world");
</script>
</body>
</html>
When the code executes, it displays two alerts, as depicted in Figures 7-1 and 7-2.
FIGURE 7-1 Using the arguments object within a function to access the first argument.
FIGURE 7-2 Using the arguments object within a function to access the second argument.
Using the arguments object and its length property as in the previous example, you can extrapo- late to any number of arguments, not only to the two shown in this example.
Chapter 4, “Working with variables and data types,” contains a section about variable scoping, including an exercise dealing with scoping inside and outside functions. The page from one of the variable scoping examples in Chapter 4 looks like this:
<!doctype html>
<html>
<head>
<title>Scoping Example</title>
<script type="text/javascript">
var aNewVariable = "is global.";
function doSomething(incomingBits) {
alert("Global variable within the function: " + aNewVariable);
alert("Local variable within the function: " + incomingBits);
} </script>
</head>
<body>
<script type="text/javascript">
doSomething("is a local variable");
alert("Global var outside the function: " + aNewVariable);
alert("Local var outside the function: " + incomingBits);
</script>
</body>
</html>
This example shows how you can globally and locally declare and scope variables from inside and outside a function. However, the example keeps the variables logically separate, in that it doesn’t use the same variable name, and then changes the variable’s value. Here’s an example in which using the same variable name might cause confusion. I find that the code I wrote years ago is confusing enough without introducing weird scoping issues, so try to avoid code like this:
function addNumbers() { firstNum = 4;
secondNum = 8;
result = firstNum + secondNum;
return result;
}
result = 0;
sum = addNumbers();
You might already have spotted the problem with this code. The var keyword is missing every- where. Even though the code explicitly initializes the result variable to 0 outside the function, the vari- able gets modified by the call to the addNumbers() function. This in turn modifies the result variable to 12, the result of adding 4 and 8 inside the function.
If you added an alert to display the result variable right after the initialization of the result variable, the alert would show 0. And if you added another alert to display the result variable after the call to the addNumbers() function, the result would show 12. I leave it to you in an exercise later to add these alerts in the right places.
The bottom line is that your life is easier when you use different names for variables inside and outside functions and always use the var keyword to initialize variables. Depending on the code contained in the function, the function might or might not have a return value. That return value is passed back to the caller, as you see in the next section.
return values
When a function finishes executing its code, it can return a value to the caller by using the return keyword. Take a look at Example 7-1 (in the listing7-1.html file in the companion content).
EXAMPLE 7-1 A simple return value example
function multiplyNums(x) { return x * 2;
}
var theNumber = 10;
var result = multiplyNums(theNumber);
alert(result);
Example 7-1 creates a function called multiplyNums with an intended input value, which will be assigned to the variable x. The function performs one task: it returns its argument multiplied by 2, as follows:
function multiplyNums(x) { return x * 2;
}
The code then creates a variable called theNumber, as follows:
var theNumber = 10;
Next, the code creates another variable called result. This variable holds the result of the call to the multiplyNums function. The multiplyNums function uses the variable theNumber as an argument:
var result = multiplyNums(theNumber);
When run, the code results in a dialog box, like the one shown in Figure 7-3.
You can place the return value anywhere within a function, not just at the end. Using a return within a conditional or after a loop is common, as shown here:
function myFunction(x) { if (x == 1) { return true;
} else {
return false;
} }
However, be careful where you place the return statement, because when the function execution gets to the return statement, the function returns immediately and won’t execute any code after that.
For example, code such as this (you can find this in the morereturnexamples.txt file in the companion content) probably won’t do what you want:
function myFunction() { var count = 0;
var firstNum = 48;
return;
var secondNum = 109;
}
This code never reaches the initialization of the variable secondNum.
More on calling functions
You nearly always invoke a function with some arguments or with empty parentheses, like this:
var result = orderFruit();
If arguments were required for that function, the function might look like this:
var result = orderFruit(type,quantity);
Omitting the parentheses to call a function can result in actions that are entirely different from what you want. Calling a function without parentheses results in the function name being returned, rather than whatever the function was supposed to return. Just as important, the function isn’t actu- ally executed.
Here’s an example. Example 7-2 (which you can find in the listing7-2.html file in the companion content) shows some basic JavaScript code.
EXAMPLE 7-2 Invoking a function
<!doctype html>
<html>
<head>
<title>Order Fruit</title>
<script type="text/javascript">
function orderFruit() { var total = 0;
// Call another function to place order return total;
} </script>
</head>
<body>
<script type="text/javascript">
var result = orderFruit();
alert("The total is " + result);
</script>
</body>
</html>
When executed, this code invokes the orderFruit() function. The orderFruit() function invokes another function (not shown) to place an order. The total is then calculated and sent back to the caller. As written, the code works fine and results in a dialog box like that shown in Figure 7-4.
FIGURE 7-4 Invoking the orderFruit() function with parentheses yields the results you’d expect.
A slight modification to the code—specifically, changing the function call to remove the parentheses—
changes the entire result:
var result = orderFruit;
The result is shown in Figure 7-5.
Anonymous/unnamed functions (function literals)
The functions you’ve seen so far are formally defined. However, JavaScript doesn’t require functions to be formally defined in this way. For example, with a function literal—also known as an unnamed, or anonymous, function—the function is defined and tied to a variable, like this:
var divNums = function(firstNum,secondNum) { return firstNum / secondNum; };
You can easily test this functionality with the javascript pseudo-protocol. Type the following code in the address bar of your browser:
javascript:var divNums = function(firstNum,secondNum) { return firstNum / secondNum; };
alert(divNums(8,2));
Anonymous functions are frequently used in object-oriented JavaScript and as handlers for events.
You see an example of this usage in Chapter 8, “Objects in JavaScript,” and in later chapters.
Closures
In JavaScript, nested functions have access to the outer function’s variables. Closures refer to the existence of variables outside a function’s normal execution context. Closures are frequently created by accident and can cause memory leak problems in web browsers if they're not handled properly.
However, closures are one of the more powerful (and advanced) areas of JavaScript.
Here’s an example of a closure:
function myFunction() { var myNum = 10;
function showNum() { alert(myNum);
}
return showNum;
}
var callFunc = myFunction();
callFunc();
In this example, the function showNum has access to the variable myNum created in the outer (myFunction) function. The variable callFunc is created in the global context and contains both the variable myNum and the function showNum().
When the callFunc variable is created, it immediately has access to the myNum variable.
Closures can be used to emulate private methods inside objects, and they have other uses, such as in event handlers. Closures are one of the more powerful and advanced concepts in JavaScript and as such aren’t appropriate to discuss at length in an introductory book. You can find more information about closures at http://msdn.microsoft.com/en-us/scriptjunkie/ff696765.aspx and elsewhere on the Internet.
Methods
The easiest way to think about methods is that they are functions defined as part of an object. That’s an oversimplification, but it suffices for now. You access a method of an object by using the dot operator (“.”). Built-in objects, such as the Math, Date, and String objects, all have methods that you’ve seen (or will soon see) in this book. Functions such as the alert() function are actually just methods of the window object, and could be written as window. alert() rather than just alert(). Chapter 8 covers objects and methods in greater detail.
note In much of the book, I use the terms method and function interchangeably. I’ll con- tinue to do so just so that you better understand that the line between these two is blurry for most uses. When a function is used in an object-oriented manner, using the term method is often clearer. When not used directly in an object-oriented manner—for exam- ple, the way you use the alert() function—using the term function is acceptable.
Defining your own functions vs. using built-in functions
As you’ve seen throughout the book, JavaScript has numerous built-in functions, or methods.
In addition to using these built-in functions, you will frequently find yourself defining your own functions. Except for trivial scripts, most scripts you write will involve your own functions.
In some cases, however, you might define a function and then later discover that JavaScript already has an equally good built-in function for that same purpose. If you find that a
JavaScript built-in function performs the same task as your own function, using the JavaScript function is usually a better idea.
A look at dialog functions
By now, you know all about the alert() function in JavaScript because you’ve seen many examples of it in previous chapters. You’ve also learned that the alert() function is just a method of the window object. This section looks at the everyday use of the alert() function in JavaScript, and two related functions of the window object.
Although the window object has several methods, for now I’d just like to highlight these three (which I call functions): alert(), confirm(), and prompt(). Because you’ve already seen too many alert() dialog boxes in the book, I won’t include another one here (thank me later). Although the prompt() function is blocked by default beginning with Internet Explorer 7, the confirm() function is still avail- able in Internet Explorer.
The confirm() function displays a modal dialog box with two buttons, OK and Cancel, like the one shown in Figure 7-6. (A modal dialog box prevents other activity or clicks in the browser until the visi- tor closes the dialog box—in this case, by clicking OK or Cancel.)
FIGURE 7-6 The confirm() JavaScript function provides a dialog box for confirming user actions.
When you click OK, the confirm() function returns true. As you might guess, when you click Cancel, the confirm() function returns false.
Like alert() and prompt(), the confirm() function creates a modal dialog box on most platforms. This can get annoying if these functions are overused or used in the wrong place. But used properly, to provide important feedback and obtain vital information, these functions can be quite useful.
Tip Don’t use the confirm() function in place of a web form to obtain user input. The web form is much better for navigation and will keep your visitors happier.
The next exercise walks you through using the confirm() function to obtain input and make a deci- sion based on that input.
Obtaining input with confirm()
1. Using Microsoft Visual Studio, Eclipse, or another editor, edit the file confirm.html in the Chapter07 sample files folder in the companion content.
2. In the page, replace the TO DO comments with the following code shown in boldface (you can find this code in the confirm.txt file in the companion content):
<!doctype html>
<html>
<head>
<title>Confirming Something</title>
<script type="text/javascript">
function processConfirm(answer) { var result = "";
if (answer) {
result = "Excellent. We'll play a nice game of chess.";
} else {
result = "Maybe later then.";
}
return result;
}
</script>
</head>
<body>
<script type="text/javascript">
var confirmAnswer = confirm("Shall we play a game?");
var theAnswer = processConfirm(confirmAnswer);
alert(theAnswer);
</script>
</body>
</html>
3. Save the page, and view it in a web browser. You are presented with a dialog box that looks like this:
4. Click OK. You see an alert() dialog box:
5. Click OK, and then reload the page.
6. You are again shown the original dialog box from the confirm() function, which asks if you’d like to play a game. This time, click Cancel. You are presented with a different alert() dialog box:
7. Click OK to close the dialog box.
The code has two major areas to examine, one within the <HEAD> portion and the other within the
<BODY> portion. The function processConfirm(answer) is created in the <HEAD> portion of the page:
function processConfirm(answer) { var result = "";
if (answer) {
result = "Excellent. We'll play a nice game of chess";
} else {
result = "Maybe later then.";
}
return result;
}
This function evaluates the value contained in the argument held in the variable answer. If the value in the answer variable evaluates to true, as it does when the visitor clicks OK, the function creates the variable result and assigns to result a string value of “Excellent. We’ll play a nice game of chess.” But, if the value in the answer variable evaluates to false, as it does when the visitor clicks Cancel, the function still creates the result variable but now assigns it the value of “Maybe later then.” Regardless of what’s held in the answer variable, processConfirm returns the result variable to the caller by using the return statement within the function. You could write this function more succinctly as:
function processConfirm(answer) { if (answer) {
return "Excellent. We'll play a nice game of chess.";
} else {
return "Maybe later then.";
} }
And even more succinctly as:
function processConfirm(answer) { var result;
(answer) ? result = "Excellent. We'll play a nice game of chess." : result = "Maybe later then.";
return result;
}
note In all likelihood, I would use the last function example to perform this task. However, I’ve found many programmers who aren’t comfortable with the ternary logic of the last example. So for readability, I’d choose the more explicit of the two:
function processConfirm(answer) { if (answer) {
return "Excellent. We'll play a nice game of chess.";
} else {
return "Maybe later then.";
} }
The JavaScript contained within the <BODY> section of the code creates the confirmation dialog box, calls the processConfirm() function, and displays the result:
var confirmAnswer = confirm("Shall we play a game?");
var theAnswer = processConfirm(confirmAnswer);
alert(theAnswer);
Like the alert() function, the confirm() function accepts a single argument, which is the message to be displayed in the dialog box. Although not necessary with the alert() function, with the confirm() function, phrasing your prompt in the form of a question or other statement that gives the visitor a choice is best. If the user really doesn’t have a choice, use the alert() function instead. An even more succinct version combines all three lines, like this:
alert(processConfirm(confirm("Shall we play a game?")));
Exercises
1. Define a function that takes one numeric argument, increments that argument, and then returns it to the caller. Call the function from within the <BODY> section of a page, and dis- play the result on the screen.
2. Define a function that accepts two numeric parameters. If the value of the first parameter is greater than the second, show an alert to the visitor. If the value of the first parameter is less than or equal to the second, return the sum of both parameters.
3. Add appropriate alert() functions to the following code so that you can see the value in the