7
Creating functions

The graphical representation shows people dining out outside the restaurants on both sides of the road. The vehicles are passing through the road at the center.

What you will learn

Functions are an essential part of program design. You can use functions to break up a large solution into individual components and to create libraries of behaviors that can be used by your programs. We have used some built-in functions (for example, alert) and created event handler functions (for example, doCheckAge). In this chapter, you’ll learn how to create and use functions of your own. You’ll see how to give functions data to work on and how a program can receive results that a function returns. Along the way, you will pick up some tips about error handling.

What makes a function?

Parameters as values

Reference arguments

Double dice

What you have learned

What makes a function?

A function is a chunk of JavaScript that has been given an identifier. A function should be defined before it is used. When JavaScript encounters a function definition, it takes the statements that provide the behavior of the function and stores them, so they are ready for use by the program. A program can call the function and the statements in the function will be performed. We’ve created and called functions already, but now is the time to take a detailed look at how they work. Let’s start with a look at a simple function that just says “hello.”

A snapshot shows a function.

This web page contains a function called greeter. The function finds an element on the screen with the ID outputParagraph and displays Hello in that element. Once the function has been defined, a program can call it. A call of a function runs the statements given when the function was defined. The greeter function doesn’t do much, but you can create functions that contain many statements. Remember that your program must define the function before it can be called.

CODE ANALYSIS

Investigating functions

Start by opening the application in the Ch07 FunctionsCh07-01 Greeter Function example code folder. This application contains an HTML page with the output paragraph and a script section containing the greeter function. Open the Developer View by pressing F12.

Question: How do I call a function in my program?

Answer: Up until now, our programs have used functions that have been provided for us by JavaScript (for example, the alert function). But the greeter function is one that we have written. However, we can call it in the same way, simply by entering the name of the function, followed by a pair of braces.

> greeter();

When you press Enter, the greeter function is called. This function does not return a result (we will look at this later) and so the console displays undefined.

<- undefined

However, you will notice that the word “Hello” has now appeared in the browser display. This was displayed by the greeter function when it ran.

A screenshot of a browser screen is displayed.

Question: Can we define functions in the console?

Answer: Yes, we can define our own functions in the console. Type the statement below, which creates a function called alerter.

> function alerter() { alert("hello"); };

Press Enter when you’ve typed the above statement, exactly as it is shown. Make sure to use the right kinds of brackets for each part.

<- undefined

The application now contains a new function called alerter. The process of defining a function does not return a value, so the console shows the result as undefined.

The JavaScript that you have just typed contains a statement that calls the alert function, but this has not run because this statement is in the body of the alerter function. Now enter a statement that calls the newly created function:

> alerter();

When you press Enter, the statement will call alerter, which will display an alert:

<- undefined
A screenshot of a browser screen is displayed.

Question: Can one function call another function?

Answer: Yes, it can. Consider the following functions:

function m2(){
    console.log("the");
}

function m3(){
    console.log("sat on");
    m2();
}
function m1(){
    m2();
    console.log("cat");
    m3();
    console.log("mat");
}

If m1 is called what will be logged in the console? The best way to figure this out is to work through the functions one statement at a time, just like the computer does when it runs the program. Remember that when a function is complete, the program’s execution continues at the statement following the function call. These functions are in the JavaScript for the Greeter page. You can find out what happens by calling function m1:

> m1();

When you press enter the m1 function is called. This then calls m2 and so on. The output is what you would expect:

the
cat
sat on
the
mat

Question: What happens if a function calls itself? For example, what if the m1 function called m1?

Answer: Making a function call itself is a bit like arranging two mirrors so that they face each other. In the mirrors, you see reflections going off into infinity. Does JavaScript go off into infinity when a function call itself? Let’s create a function and find out. Enter the following function definition:

> function mirror() { mirror(); };

The mirror function just contains one statement that calls the mirror function. What happens when we create the function. Press Enter to find out.

<- undefined

Nothing happens. Creating a function is not the same as running it. However, we now have a function called mirror that calls itself. Let’s call mirror and see what happens:

> mirror();

When you press Enter, JavaScript will find the mirror function and start obeying the statements in it. The first statement in mirror is a call of the mirror function, which JavaScript will start to execute. The program is stuck in a loop, but it does not get stuck forever. After a while, the console stops with an error:

A screenshot of a browser screen is displayed.

Each time a function is called, JavaScript stores the return address (the place it must go back to) in a special piece of memory called the “stack.” The idea is that when a running program reaches the end of a function, it grabs the most recently stored return address from the top of the stack and returns to where that address points. This means that as functions are being called and returned, the stack grows and shrinks.

However, when a function calls itself, JavaScript repeatedly adds return addresses to the stack. Each time the function calls itself, another return address is added to the stack, at the top. The stack is finite in size, and when this size is exceeded, JavaScript stops the program.

Programmers have a name for a function that works by calling itself: recursion. Recursion is occasionally useful in programs, particularly when the program is searching for values in large data structures. However, I’ve been programming for many years and have used recursion only a handful of times. I advise you to regard recursion as strong magic that you don’t need to use now (or hardly ever). Loops are usually your best bet for repeating blocks of code.

Figure 7-1 shows the form of a JavaScript function definition. We can work through each of these items in turn. The keyword function tells JavaScript that a function is being defined. JavaScript will allocate space for the function and get ready to start storing function statements. The word function is followed by the identifier of the function. We must create an identifier for each function we define. Because a function is associated with an action, it’s a very good idea to make the name reflect this. I give functions names in the form verbNoun. The verb specifies the action the function will perform, and the noun specifies the item it will work on. An example would be doMultiplicationTables.

The figure shows the syntax of 'function definition.' The syntax of 'function definition' is as follows. Function identifier left parenthesis arguments right parenthesis left brace statement right brace semicolon.

Figure 7-1 Function definition

After the function identifier, we have the arguments that are fed into the function. The arguments are separated by commas and enclosed within parentheses. Arguments provide a function with something to work on. So far, the functions we’ve created haven’t had any arguments, so there has been nothing between the two parentheses. Finally, the definition contains a block of JavaScript statements that form the body of the function. These are the statements that will be obeyed when the function is called.

Give information to functions

The greeter function shows how functions can be used, but it isn’t really that useful because it does the same thing each time it’s called. To make a function truly useful, we need to give the function some data to work on. You’ve already seen many functions that are used in this way. The alert function accepts a string to display in the alert box. The Number function accepts an input to be turned into a numeric value. We could make a version of the greeter function that accepts a message to be displayed:

function greeter(message) {
  var outputElement = document.getElementById("outputParagraph");
  outputElement.textContent = message;
}

CODE ANALYSIS

Investigating arguments

The new version of greeter is in the example application Ch07 FunctionsCh07-02 Greeter Arguments. Open this application and then open the Developer View by pressing F12.

Question: How do I give a function call an argument?

Answer: We can give a function an argument by putting something between the braces in the call of the function:

> greeter("Hello from Rob");

When you press Enter, the greeter function is called and the string Hello from Rob is passed as an argument to the function call.

<- undefined

The greeter function does not return a value, so the console displays undefined. However, you will notice that the phrase Hello from Rob has now appeared on the browser display. This was displayed by the greeter function when it ran.

A screenshot displays the greeter function.

Question: What happens if I omit the argument from the function call?

Answer: This is bad programming practice. We’ve told JavaScript that the greeter function accepts an argument, and then we failed to supply an argument when we called it. Let’s try it. Enter a call of greeter with no arguments.

> greeter();

You might think that this would cause an error. The greeter function is expecting to receive something that is missing from the call. If you’ve used other programming languages, for example C++ or C#, you will be used to getting errors if you make this mistake. However, it turns out that JavaScript is much more relaxed about this. There is no error, but there’s no greeting either:

A screenshot displays the greeter function.

This is what has happened:

  1. The JavaScript system notices that there is an argument missing from the call.

  2. It supplies the function with the value undefined for the missing argument.

  3. The function sets the textContent property of the output paragraph to undefined. This is not displayed by the browser, so the text on the screen disappears.

If we are concerned about calls with missing arguments, we can make a version of the greeter function that checks to see if it has been given an argument:

function errorGreeter(message) {
  if(message == undefined) {
    alert("No argument to greeter");
  }
  else
  {
    let outputElement = document.getElementById("outputParagraph");
    outputElement.textContent = message;
  }
}

The function above is called errorGreeter. It checks the message it has been supplied with and if the message is undefined it displays a warning alert. Otherwise, it displays the message. This function is in the scripts of the example program. Try calling errorGreeter in the browser console with a missing argument:

> errorGreeter();

When you press Enter, you will see an alert because the function was not supplied with an argument.

A screenshot of a browser screen is displayed.

If you call errorGreeter with an argument, you will see that it displays the message as it should.

Question: What happens if I call a function with too many arguments?

Answer: We could try this:

> greeter("Hello world", 1,2,3, "something else");

If you call greeter as above, JavaScript will not produce any errors, but the greeter function will ignore the extra arguments.

Arguments and parameters

From the title of this section, you might expect that we will have a difference of opinion, but in JavaScript, the word argument has a particular meaning. In JavaScript, “argument” means “that thing you give to the call of a function.”

greeter("Hello world");

In the above statement, the argument is the string Hello world. So when you hear the word “argument,” you should think of the code that is making a call of the function. In JavaScript, the word parameter means “the name within the function that represents the argument.” The parameters in a function are specified in the function definition.

function greeter(message)

This is the definition of a greeter function that has a single parameter. The parameter has the identifier message. When the function is called, the value of the message parameter is set to whatever has been given as an argument to the function call. Statements within the function can use the parameter in the same way as they could use a variable with that name.

MAKE SOMETHING HAPPEN

Parameters as values

When a function is called, the value of the argument is passed into the function parameter. What exactly does this mean? The following program contains a function (with the interesting name whatWouldIDo) that accepts a single parameter. The function doesn’t do much; it just sets the value of the parameter to 99.

function whatWouldIDo(inputValue) {
  inputValue = 99;
}

This function is part of the application in the Ch07 Creating functionsCh07-03 Parameters as values folder in the example code. Open this application and then open the Developer View by pressing F12. First, we are going to create a variable and put a value into it:

> var test=0;

When you press Enter, the console will create a variable called test that contains the value 100. We can use the test variable as an argument to the whatWouldIDo function:

> whatWouldIDo(test);

When the function has been called, the question we must consider is “What value does test now contain?” Does it contain 0 (the value set when it was created), or does it contain 99 (the value set in the function whatWouldIDo)? We can answer the question by asking the console to display the value of test:

> test
<- 0

When a function is called, the value in the argument is copied into the parameter. So any changes to the parameter will not affect the argument at all.

Multiple parameters in a function

A function can have multiple parameters. We might want a greeter function that can display text in different colors. We could add a second parameter that contains a color name:

function colorGreeter(message, colorName) {
  var outputElement = document.getElementById("outputParagraph");
  var elementColorStyle = "color:"+colorName;
  outputElement.textContent = message;
  outputElement.style=elementColorStyle;
}

This function creates a style element using a supplied color name. The style is then applied to the output element along with the greeting text. We then provide arguments giving the string to be displayed and the color of the text:

colorGreeter("Hello in Red", "red");

WHAT COULD GO WRONG

Muddled arguments

The colorGreeter function has two arguments that are mapped onto the two parameters that are used inside the function. The first argument has the greeting text, and the second argument has the name of the color to be used for the text. It is important that these arguments are supplied in the correct order.

colorGreeter("red", "Hello in Red");

This call of colorGreeter has supplied the color name before the greeting text. In other words, they are the wrong way round. This would result in the colorGreeter trying to display the message “red” in the color “Hello in Red.” This would not cause an error, but it would result in the program not doing what you want. So when we make calls to functions, we need to make sure that the arguments that are supplied are given in the same order as the parameters. You can find the colorGreeter function in the Ch07 Creating functionsCh07-04 Color Greeter folder.

Using references as function arguments

In a JavaScript program there are essentially two kinds of variable. There are variables that contain a value and variables that contain a reference to an object.

var age=12;

This statement creates a variable called age, which contains a number with the value 12.

var outputElement = document.getElementById("outputParagraph");

This statement creates a variable called outputElement, which contains a reference to an HTML element in the page document. This is how our JavaScript programs have located the page elements to be used to display information for the user. We can pass references into function calls as arguments:

A snapshot source code of a html program.

The HTML page above contains a function called makeGreen. The function makeGreen has a parameter called element. The function sets the style of the element parameter to the color green. A program can use this function to make any given HTML element green.

makeGreen(outputElement);

MAKE SOMETHING HAPPEN

Reference arguments

The function makeGreen is declared in the example application Ch07 Creating functionsCh07-05 Reference arguments folder in the example code. Open this application and then open the Developer View by pressing F12. First we are going to get a reference to the display paragraph.

> var outputElement = document.getElementById("outputParagraph");

When you press Enter, a variable called outputElement is created that contains a reference to a paragraph on the screen. Now use this variable as an argument to a call of makeGreen:

> makeGreen(outputElement);

This will cause the text of the paragraph on the web page to turn green because the makeGreen function has set the style property of the element to which it has received a reference:

A screenshot displays the output of makegreen function.

What happens if we give makeGreen the wrong kind of argument? Try this:

> makeGreen(21);

The result of this statement is that nothing happens. No error is produced even though it is not meaningful to try to set the style of a numeric value to 21. Any mistakes that you make with function arguments will not produce errors; instead, the program will just keep running.

Arrays of arguments

There is another way that we can pass arguments into a JavaScript function—an array of items. We will discuss arrays in detail in the next chapter. An array is a form of collection. We have already seen one form of collection. The unordered list that we used to display ride information in the Theme Park in Chapter 6 held elements in the form of an array of items. We used the for–of loop construction to work through the array. If you’re not sure about how this works, take a moment to return to Chapter 6 and read “Work through collections using for-of.” Within a function, the keyword arguments means the array of arguments that were given when the function was called.

The screenshot displays the array of arguments.

The function calculateSum shows how this works. It uses a for-of loop to calculate the total of all the arguments given to the function call. This total value is then displayed on the page. The function can be called with any number of numeric arguments:

calculateSum(1,2,3,4,5,6,7,8,9,10);

This would display the value 55. Of course, if you do something silly, you might not get what you expect.

calculateSum(1,2,3,"Fred","Jim","Banana");

This call of the function would not cause an error. It would display the result 6FredJimBanana. This is because of the way that JavaScript combines strings and numbers. You can find out more in Chapter 4 in the section “Working with strings and numbers.” You can find this sample code in Ch07 Creating functionsCh07-06 Argument arrays.

Returning values from function calls

A function can return a value. You have seen this in many of the programs we’ve written. Here’s an example:

var ageNo = Number(ageText);

This statement uses the Number function. The function accepts an argument (text expressing a number) and returns a value (the text as a numeric value). We can write our own functions that return a value.

Dice spots method

In Chapter 4, we created an application that displays random dice. Each time we wanted a random dice value, we had to perform some calculations. It would be useful to have these calculations in a function that we could use to get a random number of spots.

The screenshot displays the calculations in the function.

This is the function getDiceSpots, which calculates a random number of spots. (Check out the section “Creating random dice” in Chapter 4 for details of how this works.) The last statement in the function uses the JavaScript return keyword to return the calculated number to the caller. This function can be used whenever an application needs a dice value.

A screenshot explains the function doRollDice.

The function doRollDice is called to display a dice value. It calls getDiceSpots to get the value and then display it. You can see this in action in the example application Ch07 Creating functionsCh07-07 Returning values, which works in exactly the same way as the dice example in Ch04 Working with dataCh04-02 Computer Dice, but it uses the doRollDice function.

Creating customizable dice

Sometimes, a program needs a random number in a different range from the 1 to 6 provided by a die. We could use our newfound skills to make a function that accepts minimum and maximum values and then returns a random integer in that range.

A screenshot shows the code to create a customizable dice.

The function getCustomDiceSpots is given two parameters that specify the minimum and maximum values of the required random number. It works out the range of numbers that are required (the difference between the maximum and minimum values), calculates a random number in this range, and then adds that number to the minimum value to produce the number of spots. This number is then returned. One of the nice things about functions is that you don’t have to understand how they work to use them.

var health = getCustomDiceSpots(70,90);

The above statement creates a variable called health, which contains a random number in the range 70 to 90. It could be used in a video game to set the initial health value of a monster that fights the player. Sometimes, the monster would be slightly harder to kill, which would make the game more interesting to play.

The customizable dice app

I’ve used the getCustomDiceSpots function to make a dice application where the user can select the minimum and maximum values for random numbers that they want to use to play a particular game.

Figure 7-2 shows how the application is used. The user fills in the text boxes for the Min and Max values for the random number that they want and presses the Roll The Dice button to display a random number in that range.

The screenshot is displayed with a title that reads Digital Dice.

Figure 7-2 Customizable dice

The settings in Figure 7-2 will produce a value in the range 1 to 50 that could be used to play a bingo game. Let’s take a look at the code.

A screenshot displays the function DOCTYPE.
A screenshot shows coding under <p class = menuText>.

We have seen this kind of page before. There is some text to tell the user about the application. There are two input fields, which are used to get the minimum and maximum values for the random number to be produced. There is a Roll the Dice button to trigger the generation of the value and an output paragraph that displays the result. This page is very similar to the one used by the Theme Park Ride Selector application in Chapter 6. The function doRollDice is called when the user clicks the button to roll the dice.

onclick="doRollDice('minNoText','maxNoText', 'outputParagraph');"

This is the onclick attribute for the Roll the Dice button. This attribute contains a string of JavaScript code that will be obeyed when the button is clicked. If you’re not clear on how this works, take a look in the section “Using a button” in Chapter 2 for a refresh. The JavaScript that runs when the button is clicked makes a call of the function doRollDice.

doRollDice('minNoText','maxNoText', 'outputParagraph');

The doRollDice function has three arguments, which are the ID strings for the minNoText, maxNoText, and outputParagraph elements in the web page. The function gets the minimum and maximum values from elements identified by the first two arguments to the function call. It then calculates the random result and then displays the result using the output element identified in the third element. We can take a look at this function to see how it works:

A screenshot displays the function doRollDice in the program.

The function looks very small. It gets in the minimum and maximum values, calls getCustomDiceSpots to get the random value, and then displays the result. The function is small because it uses another function called getNumberFromElement to get the maximum and minimum values:

A screenshot explains the function getNumberFromelement.

This function is given the identifier of an input element on the web page as a parameter. It fetches a number from the specified input element. We can use this function in any program that needs to read numbers from the user. It gets a reference to the element with the identifier that has been supplied as a parameter, gets the text from this element, converts the text into a number, and then returns the number to the caller. The function is called twice in the dice application—once to read the maximum value and once to read the minimum value. If I had an application that needed 10 inputs to be read from the screen, I could call this function 10 times in the application.

Add error handling to an application

The Digital Dice program works well as long as we use it correctly. However, it is not without its problems. It is quite easy to enter invalid values for the minimum and maximum values. You can experiment with the application in the examples folder Ch07 Creating functionsCh07-08 Custom dice to discover what happens when it fails.

Figure 7-3 shows how the application can be used incorrectly. A minimum value of 50 and a maximum value of 2 is not correct. To make matters worse, the application has displayed a result that might be incorrect. We have no way of knowing if it has worked correctly because we are not sure how the getCustomDiceSpots function behaves if it is given incorrect maximum and minimum values. It turns out that there are also other ways to cause the program problems. A user could press Roll The Dice when the Min and Max input areas are both empty. We need to fix all these things. Fortunately, we have the JavaScript skills that we need to sort this out.

The screenshot is displayed with a title that reads Digital Dice.

Figure 7-3 Dice errors

Finding all the errors in advance

One thing that separates a good programmer from a great programmer is the way that they handle errors. A great programmer will start a project by thinking of all the things that could go wrong when the user starts to use their program. It’s unlikely that they will think of every possible error (users can be very inventive when it comes to breaking things), but they will write down all the errors they can think of and then set out to deal with each error. Then, as the project continues, a great programmer will keep looking for possible errors and keep making sure that the errors that they know about are being handled correctly. In the case of the Digital Dice application, I can think of three things that might go wrong:

  1. The user might not enter anything into the Max or Min inputs.

  2. The user might enter a number outside the correct range for one of the Max or Min inputs.

  3. The user might enter a Min value that is greater than or equal to the Max value.

Now that we have identified the errors, the next thing we need to decide is what the program should do when they are detected. If you are writing a program for a customer, you must discuss with them what is supposed to happen. Do they want the program to assume default values (perhaps a Min of 1 and a Max of 6), or do they want error messages to be displayed? Do they want the error to be a message on the screen or a pop-up alert? These are all important questions that the programmer alone can’t answer. The worst thing that can happen is that you make an assumption concerning what the customer wants. In my experience, making assumptions is a neat way of doubling your workload. You show the customer what you’ve made, they tell you it is not what they want, and you have to do it again. In the case of our customer, we have been told that the program should display a message and turn any invalid input areas on the screen red so that the user knows what to fix. So let’s see how we can use our JavaScript skills to solve this problem.

Let’s start with the error display. These are two style classes that I’m going to use to on the input elements on the web page. The menuInput style is the “normal” style. The program will set the menuInputError style to an input element that contains an invalid entry. Note that this has the background color set to red.

.menuInput {
    background-color: white;
    font-size: 1em;
    width: 2em;
}

.menuInputError {
    background-color: red;
    font-size: 1em;
    width: 2em;
}

Our application uses a function called getNumberFromElement to get a number from an input element. Let’s have a look at an improved function to deal with input errors:

A screenshot explains the function getNumberFromElement.
A screenshot displays the source code to check the range.

CODE ANALYSIS

The getNumberFromElement function

This function bears closer inspection. Here are answers to some questions about it:

Question: What does NaN mean? And what is the isNan function doing?

Answer: We first saw NaN in Chapter 4 when we wrote our first JavaScript to read numbers from the user. It is how JavaScript represents a value that is “not a number.” In this case, the function is using the Number function to convert the text entered by the user into a number. If the Number function fails, either because the text is not numeric or the text is empty, the Number function returns the value NaN because it could not create a number result. The isNaN function takes an argument and returns true if the argument is not a number. The getNumberFromElement function uses isNaN to test the result value produced by the call to Number. If the result is not a number, the function sets the style of the element to indicate that the input was in error and then returns the value NaN to the caller to indicate that a number could not be read.

Question: What are the min and max attributes? Where do they come from?

Answer: We can add min and max attributes to an HTML input element to help the browser validate numbers entered by the user. However, the browser does not enforce minimum and maximum values completely; our program must also play a part in making sure that numbers are entered in the correct range.

<input class="menuInput" type="number" id="minNoText" value="1" min="1" max="99">

The HTML above is the input element for the minimum value. The min and max attributes are set to 1 and 99 respectively. The getNumberFromElement function can get the values of these attributes and then use them to perform input validation:

var max = Number(element.getAttribute("max"));
var min = Number(element.getAttribute("min"));

The function can then use these values to validate the number entered by the user.

if(result>max || result<min){
    // fail because outside range
    element.className="menuInputError";
    return NaN;
}

This is a really good way of handing minimum and maximum values because the values are obtained from the elements on the HTML page and are not held in the JavaScript code.

Question: Why does the function sometimes return the value NaN?

Answer: We’ve discovered that it is possible for the getNumberFromElement function to be unable to deliver a result. This happens when the user doesn’t type in a numeric value or when the value they enter is out of range. The function needs a way of informing the caller that it does not have a valid result, and returning NaN is how you do this in JavaScript. This makes using a function that returns a value that is a kind of “buyer beware” proposition, as the code that called the function must test to make sure that the delivered result was valid. We will see this in action when we look at the error handing version of doRollDice.

These changes to the getNumberFromElement function have addressed the first two errors that we identified. The user must now enter a valid number or the getNumberFromElement function returns the value NaN (not a number). Now the doRollDice function needs to be updated. This version checks that the minimum and maximum values are both numbers. It also checks that the minimum value is less than the maximum value. If either of these conditions is not met, the function displays an alert.

A screenshot displays the function doRollDice in the program.

Figure 7-4 shows the error handling in action. Note that I’ve also made another change to the application, so that it now shows the user the minimum and maximum values that are allowed for each input. This is a great way to reduce the chances of any errors in the first place.

A screenshot indicates the error in the output screen.

Figure 7-4 Error handling

Local variables in JavaScript functions

Imagine several cooks working together in a kitchen. Each cook is working on a different recipe. The kitchen contains a limited number of pots and pans for the cooks to share. The cooks would need to coordinate so that two of them didn’t try to use the same pot. Otherwise, we might get sugar added to our soup and custard instead of gravy on our roast beef.

The designers of JavaScript faced a similar problem when creating functions. They didn’t want functions to fight over variables in the same way that two cooks might fight over a particular frying pan. You might think that it would be unlikely that two functions would try to use variables with the same name, but this is actually very likely.

Many programmers (including me) have an affection for the variable name i, which they use for counting. If two functions use a variable called i and one function calls the other function, this could lead to programs that don’t work properly because the second function might change i to a value that the first function didn’t expect.

JavaScript solves this problem by providing a way for each function to have its own local variable space. This is the programming equivalent of giving each cook their own personal set of pots and pans. Any function can declare a local variable called i that is specific to that function call. We declare a variable as local by using the keyword var.

function fvar2() {
  var i=99;
}

function fvar1(){
  var i=0;

  fvar2();

  console.log("The value of i is:" + i);
}

When a function returns, all local variables are destroyed. The code above shows two functions that contain local variables. Both fvar1 and fvar2 use a variable called i. If we call f1var, JavaScript follows this sequence:

  1. The function fvar1 is called.

  2. The first statement of fvar1 creates a variable called i and sets it to 0.

  3. The second statement of fvar1 makes a call to fvar2.

  4. The first and only statement of fvar2 creates a variable called i and sets it to 99.

  5. The function fvar2 finishes and control returns to the third statement of fvar1.

  6. The third statement of fvar1 prints out the value of i.

The question we must consider is this: “What value is displayed in the console?” Is it the value 0 (which is set inside fvar1), or is it 99 (which is set inside fvar2)? If you’ve read the first part of this section, you know the value that will be printed is 0. The variables both have the same name (they are both called i), but they each “live” in different functions.

JavaScript uses the word scope when talking about variable lifetimes. The scope of a variable is that part of a program in which a variable can be used. Each version of i has a scope that is limited to the function body in which it is declared This form of isolation is called encapsulation. Encapsulation means that the operation of one function is isolated from the operation of other functions. Different programmers can work on different functions with no danger of problems being caused by variable names clashing with each other. Now take look at this pair of functions:

function f2() {
  i=99;
}

function f1(){
  i=0;

  f2();

  console.log("The value of i is:" + i);
}

Can you spot the difference? These two functions don’t use the keyword var to declare their variables. Is this important? Yes. It turns out that variables declared without the var keyword are made global to the whole application, so f1 and f2 are now sharing a single global variable called i. If we call the function f1, it will print the value 99 because the call of f2 will change the value of the global variable i. This means that you should always use var to declare variables in your functions unless you specifically want to share them. In Chapter 4, in the section “Global and local variables,” we discovered a situation where a program needs to have a variable that has global scope. Now we are starting to understand how this works.

Local variables using let

In Chapter 6, in the section “The JavaScript for loop,” we discovered that we could declare local variables using the keyword let. Variables declared using let are discarded when a program leaves the block of statements where they were declared, whereas variables declared using var are discarded when the program leaves the function in which they are declared.

A screenshot displays the local variables.

The function letDemo shows how this all works. It contains two versions of i. The first version is declared as var and exists for the entire function. The second version is declared inside a block and is discarded when the program leaves that block. Note that within the block it is not possible to use the outer version of i because any references to i will use the local version. In this case, we say that the outer variables is scoped out. The function also contains a variable called j, which is declared inside the inner block. However, because j is declared as var, it can be used anywhere inside the function. These functions are declared in the example program in the Ch07 Creating functionsCh07-10 Variable scope folder.

If you find this confusing, then I apologize. The best way to understand it is to consider the problem that they are trying to solve (stopping lots of cooks fighting over the same pots and pans) and then work from there. The most important point is to always use var or let when you create a variable. Otherwise, you may find yourself a victim of very strange bugs in your programs.

MAKE SOMETHING HAPPEN

Double dice

Quite a few games use two dice rather than one. Make a version of the dice program that displays the results from two dice. You could even make this super-customizable so that the user can select the range of values to be produced by each die. If you are bit stuck with this, remember that there is nothing wrong with the onClick behavior of a button calling two methods. And that two dice are just one dice (or die) times two. Take a look at my example solution in the examples at Ch07 Creating functionsCh07-11 Two Dice to discover the sneaky way I made the program work.

What you have learned

In this chapter, you learned how to take a block of code and turn it into a function that can be used from other parts of the program.

  1. You’ve seen that a function contains a header that describes the function, and a block of code that is the body of the function. The function header supplies the name of the function and any parameters that are accepted by the function. When a function is called, the programmer supplies an argument that matches each parameter.

  2. Parameters are items that the function can work on. They are passed by value, in that a copy is made of the argument given in the function call. If the function body contains statements that change the value of the parameter, this change is local to the function body. When an object (for example, a paragraph that has been obtained using the getElementById method) is used as an argument to a function call, the function receives a reference to the object. This allows code in the function body to interact with attributes in the objects, as we saw with the makeGreen function above.

  3. A function can regard parameters as an array and can work through the arguments supplied to the function by using the arguments keyword.

  4. A function returns a single value. This is achieved by using the return statement, which can be followed by a value to be returned. If no value is returned or the function does not perform a return statement, the function will return a special JavaScript value called undefined, which is used to denote a missing value.

  5. The scope of a variable in a program is that part of the program in which the variable can be used. Variables created inside the body of a function using the keyword var have a scope that is local to the function and cannot be used by statements outside that function.

  6. When creating software, it is important to consider potential errors at the start of the project rather than finding out about them later.

Here are some questions that you might like to ponder about the use of functions in programs:

Does using functions in programs slow down the program?

Not normally. There is a certain amount of work required to create the call of a function and then return from it, but this is not normally an issue. The benefits of functions far outweigh the performance issues.

Can I use functions to spread work around a group of programmers?

Indeed, you can. This is a very good reason to use functions. There are several ways that you can use functions to spread work around. One popular way is to write placeholder functions and build the application from them. A function will have the correct parameters and return value, but the body will do very little. As the program develops, programmers fill in and test each function in turn.

What is the maximum number of arguments that you can give to a function call?

We have seen that you can add lots of arguments to a call of a function. JavaScript does not place a limit on how many arguments you can pass in, but if you find yourself passing more than seven or eight, I’d advise you to think about how you are delivering the information to your function. If you want to pass a number of related items into a function, you might want to create an object (which we will explore in the next chapter) and pass in a reference to the object, rather than passing in lots of different values.

What is the difference between var and let when creating variables inside a function body?

Great question. Both keywords can be used to create a variable that exists within the block of code that is a function body. The difference between the two is that a variable created using var will exist within the function body from that point onward. A variable created using let will disappear at the end of the block in which it is created.

I’m still not clear on the difference between var and let in JavaScript. Why do we have them?

Remember that the problem that we are solving is that we don’t want a program to fail because programmers put values with different meanings into the same variable. If one part of a program used a variable called total to hold the total sales and another part used a variable called total to hold the total price, the program would fail. You would have the same problems if you used a single pan to make both custard and gravy while cooking a meal.

A variable created with the let keyword only exists within the block where it is declared, which means that it cannot be affected by statements running outside that block. This would be like you grabbing a clean pan, making the custard, and then washing the pan and putting it away before it was used for anything else. The var keyword allows you to create a variable that exists from the point of declaration and can be used to share a value around parts of a program or function.

Generally, you should create variables by using the let keyword and only use var if you really want the value in the variable to be used in other places in the function body. Note that a variable in a function that was created with the keyword var will disappear when the program exits the function.

How do I come up with names for my functions?

The best functions have names given in a verb-noun form. getNumberFromElement is a good name for a function. The first part indicates what it does, and the second part indicates where the value comes from. I find that thinking of function names (and variable names, for that matter) can be quite hard at times.

What do I do if I want to return more than one value from a function?

JavaScript functions can only return a single value. However, in the next chapter we will discover how to create data structures that can contain multiple values that can be returned by functions.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.22.181.209