We have worked with many pre-defined JavaScript methods and functions. Some examples are:
alert()
prompt()
parseFloat()
document.write()
today.getYear()
/* where "today" is a variable
containing a Date object */
A function is a named chunk of JavaScript code. A method is a
function associated with some object. In the examples above, we used
a method associated with the document object in the predefined
variable document and a method associated a date object in
a variable called today.
When a function's name is used with parentheses (containing arguments, if any), the code associated with that name is executed. This is called invoking or calling the function.
Today we'll learn why we would want to define our own functions, how to define functions, and how to use functions.
As motivation, let's return to an example that we looked at when we learned how to write forms. Recall that we wrote a program that contained a form that looked like this:
One way to write code for this — and the way we wrote it be before — is:
<FORM name = "the_form"> Number 1: <input type="text" name="field_one"> <br> Number 2: <input type="text" name="field_two"> <br> <INPUT type = "button" value = "multiply them!" onClick = "var x = window.document.the_form.field_one.value; var y = window.document.the_form.field_two.value; var p = x * y; alert(x + ' times ' + y + ' is: ' + p);"> </FORM>
onClick code getting ... too long?Indeed. Wouldn't it be nice if we had a function, say,
multiply2numbers(), that contained all the code in the
event handler? Then we could just execute that code by simply saying:
<FORM name = "the_form">
Number 1: <input type="text" name="field_one"> <br>
Number 2: <input type="text" name="field_two"> <br>
<INPUT type = "button"
value = "multiply them!"
onClick = "multiply2numbers();">
</FORM>
This should remind you of what we have been doing with the pre-defined
methods and functions that JavaScript has provided to us. If we had such a
function, our code would be more readable (don't you agree?) and easier to
debug. And, just like with pre-defined functions, this also would allow
us to re-use our code by invoking multiply2numbers() in
another context or multiple times!
In fact, JavaScript has provided a way for us to define our own functions:
<HTML> <HEAD> <TITLE> The function template</TITLE> <SCRIPT TYPE="text/JavaScript"> // comment about your lovely function function functionName() { . . . JavaScript code to define the function goes here . . . } </SCRIPT> </HEAD> <BODY> ... Here is where you would invoke (or call) your function </BODY> </HTML>
To define your own function you need:
It is also considered good practice to put a comment before the function describing what the parameters are for, what value gets computed, what actions are performed, etc. Anything that isn't obvious from the code. (Comments that just repeat the code in English are bad.)
Here is one way to re-write our example using a function:
<HEAD> <SCRIPT TYPE="text/JavaScript"> // Multiply inputs from the_form function multiply2numbers() { var x = window.document.the_form.field_one.value; var y = window.document.the_form.field_two.value; var p = x * y; alert(x + ' times ' + y + ' is: ' + p);" } </SCRIPT> </HEAD> <BODY> <FORM name = "the_form"> Number 1: <input type="text" name="field_one"> <br> Number 2: <input type="text" name="field_two"> <br> <INPUT type = "button" value = "multiply them!" onClick = "multiply2numbers();"> </FORM> </BODY>
Note the distinction between the function definition and the function invocation. The function is defined in the head of the document. Unless it is invoked, the function will not execute. In our example, the function is invoked in the event handler in the body of the document. If the click event never arises, the function will never execute.
<HEAD> <TITLE> Some thoughts </TITLE> <SCRIPT TYPE="text/JavaScript"> // this function prints some thoughts function thoughts() { document.write("I'm so glad that I'll never fit in<br>"); document.write("That will never be me<br>"); document.write("Outcasts and girls with ambition<br>"); document.write("That's what I wanna see<br>"); document.write(" <span style\"font-size: smaller\">(Pink)</span>"); } </SCRIPT> </HEAD> <BODY> <script type="text/JavaScript"> thoughts(); </script> </BODY>
Click to see the thoughts function being called
multiple times. Note that you can call a function from the body of an
HTML page (using the tag SCRIPT), not only from within an
event handler.
The ability to write something once and use it over and over is called modularity, a central principle in software engineering. Building programs out of reusable, mix and match units makes code easier to write, because you can write and debug a function once and then use it over and over again; and also easier to understand, because you can read and understand the function once and then know what's happening whenever it's used.
So far in this course, you could count on things happening in a web page in a sensible order: top to bottom and left to right. If one tag comes before another in the text of the web page, it happens first. This sensible ordering didn't change when we got to JavaScript: it also went top to bottom and left to right. Then we got to conditionals, and things got a little odd, because we could now skip some lines of code. Still, we never went backwards or anything foolish like that. Alas, not any more.
The order of execution with functions is that the caller executes first, top to bottom, but when the caller gets to the function call, control transfers to the "callee" (the function), which then executes top to bottom, and, when the function gets to the end, control returns to the caller, which continues from where it left off.
This all sounds very abstract, so let's use a concrete example with lots of alerts. Consider the following code:
<script type="text/JavaScript">
function fred()
{
alert("Fred is executing");
}
function ethel()
{
alert("Started executing Ethel, about to execute Fred");
fred();
alert("Finished with Fred, returning from Ethel");
}
alert("This is the main code, about to execute Fred.");
fred();
alert("back in the main code, about to execute Ethel.");
ethel();
alert("back in the main code, all done.");
</script>
As you can see, the body of a function follows the same top-to-bottom, left-to-right execution rules that we've always had. However, when the computer gets to a function invocation (call), it jumps to the beginning of the function, executes that, and, when the function is done, returns to where it jumped from. Thus, it takes a "round-trip" journey to the function code. If the function calls another function, there is another round-trip within the outer round-trip. (These levels of round-trips can be embedded as deeply as we like.)
The thing to keep in mind, then, is that your function is not executed when the browser reads it, but only when some code invokes (calls) your function.
As you may have observed already, the
multiply2numbers() function is not as flexible as it
should be. Specifically, the two numbers that it multiplies are always
found on the_form. This is because these form elements are "hard wired"
— that is,
it is written explicitly in the function's code. Can we do something to make
multiply2numbers() more flexible? Wouldn't it be better if we could use
multiply2numbers() to multiply any two numbers, not just those
two numbers on the_form?
We can do this by giving
two parameters to the function, like the argument when we call the
parseFloat() function:
var myNumber = parseFloat(myStringNumber);
With this in mind we can change the function as follows:
<HEAD> <SCRIPT TYPE="text/JavaScript"> function multiply2numbers(x, y) { var p = x * y; alert(x + ' times ' + y + ' is: ' + p);" } </SCRIPT> </HEAD> <BODY> <FORM name = "the_form"> Number 1: <input type="text" name="field_one"> <br> Number 2: <input type="text" name="field_two"> <br> <INPUT type = "button" value = "multiply them!" onClick = "multiply2numbers(window.document.the_form.field_one.value, window.document.the_form.field_two.value);"> </FORM> </BODY>
Notice the two added parameters named
x and y. Note too that since the function
definition now includes parameters, the function must be invoked
differently than before. Specifically,when the function is invoked,
two values must be passed into the function within the
parantheses. These values are then associated with the parameters in
the function in the order in which they are passed. That is, for our
example, window.document.the_form.field_one.value is
associated with x and
window.document.the_form.field_two.value is associated
with y. That is, the value
'window.document.the_form.field_one.value' is known inside the
function as x and the
value'window.document.the_form.field_two.value' is known
inside the function as y. Or, another way of saying this
is that any reference to x inside the function
multiply2numbers() uses the value
'window.document.the_form.field_one.value'and any reference to
y inside the function multiply2numbers()
uses the value
'window.document.the_form.field_two.value'.
We saw earlier that defining a function allows us to repeatedly execute code. Now that we have added parameters to the function, each time the function is invoked we can change the numbers being multiplied. For example we could multiply two numbers from a different form:
<FORM name = "form2"> Number 1: <input type="text" name="field_one"> <br> Number 2: <input type="text" name="field_two"> <br> <INPUT type = "button" value = "multiply them!" onClick = "multiply2numbers(window.document.form2.field_one.value, window.document.form2.field_two.value);"> </FORM>
Or, we could multiply two numbers that have nothing to do with a form:
<script type="text/JavaScript">
var num1 = prompt("Please input a number:");
var num2 = prompt("Please input another number:");
onClick = "multiply2numbers(num1, num2);">
</script>
To reiterate, when we call the function, we pass in a value for each parameter. These values will take the place of the parameters in every piece of the function.
Parameters increase modularity by increasing the possibilities for code reuse.
Let's now explore an example using
user-defined functions. Write an HTML program to make a similar
page. In your program, define a global variable called
amountToPay which will store the user's total shopping
bill. Be careful to initialize it properly. Define a function
addToTotal() that updates and displays (via an
alert()) amountToPay each time the user
makes a purchase. addToTotal() should take a single
parameter: the price of the purchased item. Your page should have a
single form with multiple buttons (in our case, there are five). Each
button should include an event handler that invokes
addToTotal(), passing in the cost of the item purchased.
After you've worked on it on your own, you can view the source to see
the solution.
Things to note about functions:
HEAD of a document.
BODY of a document.
wisdom();
<SCRIPT> tags or an event handler.
Optional reading: Thau Chapter 6.
© Computer Science 110 Staff
This work is licensed under a Creative Commons License
Date Modified:
Tuesday, 08-Apr-2008 13:33:51 EDT