A function is something that performs a particular task. Take a pocket calculator as an example. It provides lots of basic calculations, such as addition and subtraction. However, many also have function keys that do something more complex. For example, some calculators have a button for calculating the square root of a number, and others even provide statistical functions, such as calculating an average. Most of these functions could be done using just the basic mathematical operations of add, subtract, multiply, and divide. However, the number of calculations needed could be quite extensive, so the calculation is greatly simplified for the user if she can just use one button to do all the stages of the calculation. All she needs to do is provide the data—numbers in this case—and the function key does all the rest.
Functions in JavaScript work a little like the function buttons on a pocket calculator; they encapsulate a block of code that performs a certain task. Over the course of the book so far, we have come across a number of handy built-in functions that perform a certain task, such as the parseInt() and parseFloat() functions, which convert strings to numbers, and the isNaN() function, which tells us whether a particular value can be converted to a number. Some of these functions return data, such as parseInt(), which returns an integer number; others simply perform an action, but return no data. You'll also notice that some functions can be passed data, while others cannot. For example, the isNaN() function needs to be passed some data, which it checks to see if it is NaN. The data that a function requires to be passed is known as its parameter(s).
As we work our way through the book, we'll be coming across many more useful built-in functions, but wouldn't it be great to be able to write our own functions? Having worked out, written, and debugged a block of code to perform a certain task, it would be nice to be able to call it again and again when we need it. JavaScript gives us the ability to do just that, and this is what we'll be concentrating on in this section.
Creating and using your own functions is very simple. Figure 3-13 shows an example of a function.
You've probably already realized what this function does and how the code works. Yes, it's the infamous Fahrenheit to centigrade conversion code again.
Each function you define in JavaScript must be given a unique name for that particular page. The name comes immediately after the function keyword. To make life easier for yourself, try using meaningful names so that when you see it being used later in your code, you'll know exactly what it does. For example, a function that takes as its parameters someone's birthday and today's date and returns the person's age could be called getAge(). However, the names you can use are limited in a similar way to variable names. For example, you can't use words reserved by JavaScript, so you couldn't call your function with() or while().
The parameters for the function are given in parentheses after the function's name. A parameter is just an item of data that the function needs to be given to do its job. Usually, not passing the required parameters will result in an error. A function can have zero or more parameters, though even if it has no parameters you must still put the open and close parentheses after its name. For example, the top of your function definition must look like the following:
function myNoParamFunction()
We then write the code, which the function will execute when called on to do so. All the function code must be put in a block by using a pair of curly braces.
Functions also give us the ability to return a value from a function to the code that called it. We use the return statement to return a value. In the example function given earlier, we return the value of the variable degCent, which we have just calculated. You don't have to return a value if you don't want to, but you should always include a return statement at the end of your function, although JavaScript is a very forgiving language and won't have a problem if you don't use a return statement at all.
When JavaScript comes across a return statement in a function, it treats it a bit like a break statement in a for loop—it exits the function, returning any value specified after the return keyword.
You'll probably find it useful to build up a "library" of functions that you use frequently in JavaScript code, which you can cut and paste into your page whenever you need them.
Having created our functions, how do we use them? Unlike the code we've seen so far that executes when JavaScript reaches that line, functions only execute if you ask them to, which is termed calling or invoking the function. We call a function by writing its name at the point we want it to be called and making sure that we pass any parameters it needs, separated by commas. For example
myTemp = convertToCentigrade(212);
This line would call the convertToCentigrade() function we saw earlier, passing 212 as the parameter and storing the return value from the function (that is, 100) in the myTemp variable.
Let's have a go at creating our own functions now, taking a closer look at how parameters are passed. Parameter passing can be a bit confusing, so we'll first create a simple function that takes just one parameter (the user's name) and writes it to the page in a friendly welcome string. First, we need to think of a name for our function. A short, but descriptive, name is writeUserWelcome(). Now we need to define what parameters the function expects to be passed. There's only one parameter—the user name. Defining parameters is a little like defining variables—we need to stick to the same rules for naming, so that means no spaces, special characters, or reserved words. Let's call our parameter userName. We need to add it inside parentheses to the end of the function name (note we don't put a semicolon at the end of the line).
function writeUserWelcome(userName)
OK, now we have defined our function name and its parameters; all that's left is to create the function body—that is, the code that will be executed when the function is called. We mark out this part of the function by wrapping it in curly braces.
function writeUserWelcome(userName) { document.write("Welcome to my website " + userName + "<br>"); document.write("Hope you enjoy it!"); }
The code is simple enough; we write out a message to the web page using document.write(). You can see that userName is used just as we'd use any normal variable; in fact, it's best to think of parameters just as normal variables. The value that the parameter has will be that specified by the JavaScript code where the function was called.
Let's see how we would call this function.
writeUserWelcome("Paul");
Simple, really—just write the name of the function we want to call, and then in parentheses add the data to be passed to each of the parameters, here just one. When the code in the function is executed, the variable userName, used in the body of the function code, will contain the text "Paul".
Suppose we wanted to pass two parameters to our function—what would we need to change? Well, first we'd have to alter the function definition. Imagine that the second parameter will hold the user's age—we could call it userAge since that makes it pretty clear what the parameter's data represents. Here is the new code:
function writeUserWelcome(userName, userAge) { document.write("Welcome to my website" + userName + "<br>"); document.write("Hope you enjoy it<br>"); document.write("Your age is " + userAge); }
We've added a line to the body of the function that uses the parameter we have added. To call the function, we'd write the following:
writeUserWelcome("Paul",31);
The second parameter is a number so there is no need for quotes around it. Here the userName parameter will be Paul, and the second parameter userAge will be 31.
Let's rewrite our temperature converter page using functions. You can cut and paste most of this code from ch3_examp4.htm—the parts that have changed have been highlighted. Once you've finished, save it as ch3_examp5.htm.
<html> <body> <script language="JavaScript" type="text/javascript"> function convertToCentigrade(degFahren) { var degCent; degCent = 5/9 * (degFahren - 32); return degCent; } var degFahren = new Array(212, 32, -459.67); var degCent = new Array(); var loopCounter; for (loopCounter = 0; loopCounter <= 2; loopCounter++) { degCent[loopCounter] = convertToCentigrade(degFahren[loopCounter]); } for (loopCounter = 2; loopCounter >= 0; loopCounter--) { document.write("Value " + loopCounter + " was " + degFahren[loopCounter] + " degrees Fahrenheit"); document.write(" which is " + degCent[loopCounter] + " degrees centigrade<br>"); } </script> </body> </html>
When you load this page into your browser, you should see exactly the same results that you had with ch3_examp4.htm.
At the top of our script block we declare our convertToCentigrade() function. We saw this function earlier:
function convertToCentigrade(degFahren) { var degCent; degCent = 5/9 * (degFahren - 32); return degCent; }
If you're using a number of separate script blocks in a page, it's very important that the function is defined before any script calls it. If you have a number of functions, you may want to put them all in their own script block at the top of the page—between the <head> and </head> tags is good. That way you know where to find all your functions, and you can be sure that they have been declared before they have been used.
You should be pretty familiar with how the code in the function works. We declare a variable degCent, do our calculation, store its result in degCent, and then return degCent back to the calling code. The function's parameter is degFahren, which provides the information the calculation needs.
Following the function declaration is the code that executes when the page loads. First we define the variables we need, and then we have the two loops that calculate and then output the results. This is mostly the same as before, apart from the first for loop.
for (loopCounter = 0; loopCounter <= 2; loopCounter++)
{
degCent[loopCounter] = convertToCentigrade(degFahren[loopCounter]);
}
The code inside the first for loop puts the value returned by our function convertToCentigrade() into the degCent array.
There is a subtle point to the code in this example. Notice that we declare the variable degCent within our function convertToCentigrade(), and we also declare it as an array after the function definition.
Surely, this isn't allowed?
Well, this leads neatly on to the next topic of this chapter—variable scope.
What do we mean by scope? Well, put simply, it's the scope or extent of a variable's availability—which parts of our code can access a variable and the data it contains. Any variables declared in a web page outside of a function will be available to all script on the page, whether that script is inside a function or otherwise—we term this a global or page level scope. However, variables declared inside a function are visible only inside that function—no code outside the function can access them. So, we could declare a variable degCent in every function we have on a page and once on the page outside any function. However, we can't declare the variable more than once inside any one function or more than once on the page outside the functions. Note that reusing a variable name throughout a page in this way, while not illegal, is not standard good practice—it can make the code very confusing to read.
Function parameters are similar to variables: They can't be seen outside the function, and while we can declare a variable in a function with the same name as one of its parameters, it would cause a lot of confusion and easily lead to subtle bugs being overlooked. It's therefore bad coding practice and best avoided, if only for the sake of your sanity when it comes to debugging!
So what happens when the code inside a function ends and execution returns to the point the code was called? Do the variables defined within the function retain their value when we call the function the next time?
The answer is no; variables not only have the scope property—where they are visible—they also have a lifetime. When the function finishes executing, the variables in that function die and their values are lost, unless we return one of them to the calling code. Every so often JavaScript performs garbage collection (which we talked about in the last chapter), whereby it scans through the code and sees if any variables are no longer in use; if so, the data they hold is freed from memory to make way for other variables.
Given that global variables can be used anywhere, why not make all of them global? Global variables are great when you need to keep track of data on a global basis. However, because they are available for modification anywhere in your code, it does mean that if they are changed incorrectly due to a bug, that bug could be anywhere within the code, making debugging difficult. It's best, therefore, to keep global variable use to a minimum, though sometimes they are a necessary evil, for example, when you need to share data among different functions.