User-Defined Functions

We have worked with many pre-defined JavaScript methods and functions. Some examples are:

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:

Number 1:
Number 2:

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>

Hey, isn't the 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!

Functions: Power to the User!

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.)

How to Define a Function

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.

A More Poetic Example...

<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.

Sequence of Execution

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>
Exercise 1 Write down the order that you think the alerts in the preceding code will occur. Do this by writing numbers down next to the lines: 1 for the alert that will happen first, then 2, and so forth. When you've made your guesses, click on the following button to see what does happen.

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.

Function Parameters

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.

Exercise 2

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.

Summary

Things to note about functions:

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