Functions - Fundamentals - JavaScript for Kids: A Playful Introduction to Programming (2015)

JavaScript for Kids: A Playful Introduction to Programming (2015)

Part I. Fundamentals

Chapter 8. Functions

A function is a way to bundle code so that it can be reused. Functions allow us to run the same piece of code from multiple places in a program without having to copy and paste the code repeatedly. Also, by hiding long bits of code in a function and giving it an easy-to-understand name, you’ll be better able to plan out your code because you can focus on organizing your functions rather than all of the little code details that make them up. Splitting up your code into smaller, more manageable pieces allows you to see the bigger picture and think about how your programs are structured at a higher level.

You’ll find functions really useful when you need to repeatedly perform a calculation or action throughout a program. Earlier in the book, you used various functions such as Math.random, Math.floor, alert, prompt, and confirm. In this chapter, you’ll learn how to create your own functions.

The Basic Anatomy of a Function

Figure 8-1 shows how a function is built. The code between the curly brackets is called the function body, just as the code between the curly brackets in a loop is called the loop body.

The syntax for creating a function

Figure 8-1. The syntax for creating a function

Creating a Simple Function

Let’s create a simple function that prints Hello world!. Enter the following code in the browser console. Use SHIFT-ENTER to start each new line without executing the code.

var ourFirstFunction = function () {

console.log("Hello world!");

};

This code creates a new function and saves it in the variable ourFirstFunction.

Calling a Function

To run the code inside a function (the function body), we need to call the function. To call a function, you enter its name followed by a pair of opening and closing parentheses, as shown here.

image with no caption

ourFirstFunction();

Hello world!

Calling ourFirstFunction executes the body of the function, which is console.log("Hello world!");, and the text we asked to be printed is displayed on the next line: Hello world!.

But if you call this function in your browser, you’ll notice that there’s a third line, with a little left-facing arrow, as shown in Figure 8-2. This is the return value of the function.

Calling a function with an undefined return value

Figure 8-2. Calling a function with an undefined return value

A return value is the value that a function outputs, which can then be used elsewhere in your code. In this case, the return value is undefined because we didn’t tell the function to return any particular value in the body of the function. All we did was ask it to print a message to the console, which is not the same as returning a value. A function always returns undefined unless there is something in the function body that tells it to return a different value. (We’ll look at how to specify a return value in Returning Values from Functions.)

NOTE

In the Chrome console and in the code listings throughout this book, return values are always color-coded based on data type, while text printed with console.log is always plain black.

Passing Arguments into Functions

ourFirstFunction just prints the same line of text every time you call it, but you’ll probably want your functions to be more flexible than that. Function arguments allow us to pass values into a function in order to change the function’s behavior when it’s called. Arguments always go between the function parentheses, both when you create the function and when you call it.

The following sayHelloTo function uses an argument (name) to say hello to someone you specify.

var sayHelloTo = function (name) {

console.log("Hello " + name + "!");

};

We create the function in the first line and assign it to the variable sayHelloTo. When the function is called, it logs the string "Hello " + name + "!", replacing name with whatever value you pass to the function as an argument.

Figure 8-3 shows the syntax for a function with one argument.

The syntax for creating a function with one argument

Figure 8-3. The syntax for creating a function with one argument

To call a function that takes an argument, place the value you’d like to use for the argument between the parentheses following the function name. For example, to say hello to Nick, you would write:

sayHelloTo("Nick");

Hello Nick!

Or, to say hello to Lyra, write:

sayHelloTo("Lyra");

Hello Lyra!

Each time we call the function, the argument we pass in for name is included in the string printed by the function. So when we pass in "Nick", the console prints "Hello Nick!", and when we pass in "Lyra", it prints "Hello Lyra!".

Printing Cat Faces!

One reason to pass an argument into a function might be to tell it how many times to do something. For example, the function drawCats prints cat faces (like this: =^.^=) to the console. We tell the function how many cats to print using the argument howManyTimes:

image with no caption

var drawCats = function (howManyTimes) {

for (var i = 0; i < howManyTimes; i++) {

console.log(i + " =^.^=");

}

};

The body of the function is a for loop that loops as many times as the howManyTimes argument tells it to (since the variable i starts at 0 and repeats until it increments to howManyTimes minus 1). Each time through the loop, the function logs the string i + " =^.^=".

Here’s what happens when we call this function with the argument 5 for howManyTimes:

drawCats(5);

0 =^.^=

1 =^.^=

2 =^.^=

3 =^.^=

4 =^.^=

Try it out with howManyTimes equal to 100 to print 100 cat faces!

Passing Multiple Arguments to a Function

You can pass more than one value into a function using multiple arguments. To add another argument, enter the arguments between the parentheses after the function keyword, separating them by commas. Figure 8-4 shows the syntax for a function with two arguments.

The syntax for creating a function with two arguments

Figure 8-4. The syntax for creating a function with two arguments

The following function, printMultipleTimes, is like drawCats except that it has a second argument called whatToDraw.

var printMultipleTimes = function (howManyTimes, whatToDraw) {

for (var i = 0; i < howManyTimes; i++) {

console.log(i + " " + whatToDraw);

}

};

The printMultipleTimes function prints the string you enter for whatToDraw as many times as you specify with the argument howManyTimes. The second argument tells the function what to print, and the first argument tells the function how many times to print it.

image with no caption

When calling a function with multiple arguments, insert the values you wish to use between the parentheses following the function name, separated by commas.

For example, to print out cat faces using this new printMultipleTimes function, you’d call it like this:

printMultipleTimes(5, "=^.^=");

0 =^.^=

1 =^.^=

2 =^.^=

3 =^.^=

4 =^.^=

To have printMultipleTimes print a happy face four times, you could do this:

printMultipleTimes(4, "^_^");

0 ^_^

1 ^_^

2 ^_^

3 ^_^

When we call printMultipleTimes, we pass in the arguments 4 for howManyTimes and "^_^" for whatToDraw. As a result, the for loop loops four times (with i incrementing from 0 to 3), printing i + " " + "^_^" each time.

To draw the character (>_<) two times, you could write:

printMultipleTimes(2, "(>_<)");

0 (>_<)

1 (>_<)

In this case, we pass in 2 for howManyTimes and "(>_<)" for whatToDraw.

Returning Values from Functions

The functions we’ve looked at so far have all printed text to the console using console.log. That’s an easy and useful way to make JavaScript display values, but when we log a value to the console, we aren’t able to use that value later in the program. What if you want your function to output that value so that you can keep using it in other parts of your code?

As mentioned earlier in this chapter, the output of a function is called the return value. When you call a function that returns a value, you can use that value in the rest of your code (you could save a return value in a variable, pass it to another function, or simply combine it with other code). For example, the following line of code adds 5 to the return value of the call to Math.floor(1.2345):

image with no caption

5 + Math.floor(1.2345);

6

Math.floor is a function that returns the number you pass to it, rounded down to the nearest whole number. When you see a function call like Math.floor(1.2345), imagine replacing it with the return value of that function call, which is the number 1.

Let’s create a function that returns a value. The function double takes the argument number and returns the result of number * 2. In other words, the value returned by this function is twice the number supplied as its argument.

var double = function (number) {

➊ return number * 2;

};

To return a value from a function, use the keyword return, followed by the value you want to return. At ➊, we use the return keyword to return the value number * 2 from the double function.

Now we can call our double function to double numbers:

double(3);

6

Here, the return value (6) is shown on the second line. Even though functions can take multiple arguments, they can return only one value. If you don’t tell the function to return anything, it will return undefined.

Using Function Calls as Values

When you call a function from within a larger piece of code, the function’s return value is used wherever that function call was placed. For example, let’s use our double function to determine the result of doubling two numbers and then adding the results:

double(5) + double(6);

22

In this example, we call the double function twice and add the two return values together. You can think of the call double(5) as the value 10 and the call double(6) as the value 12.

You can also pass a function call into another function as an argument, and the function call will be substituted with its return value. In this next example we call double, passing the result of calling double with 3 as an argument. We replace double(3) with 6 so thatdouble(double(3)) simplifies to double(6), which then simplifies to 12.

double(double(3));

12

Here’s how JavaScript calculates this:

image with no caption

The body of the double function returns number * 2, so at ➊ we replace double(3) with 3 * 2. At ➋ we replace 3 * 2 with 6. Then at ➌, we do the same thing and replace double(6) with 6 * 2. Finally, at ➍, we can replace 6 * 2 with 12.

Using Functions to Simplify Code

In Chapter 3, we used the methods Math.random and Math.floor to pick random words from arrays and generate random insults. In this section, we’ll re-create our insult generator and simplify it by creating functions.

A Function to Pick a Random Word

Here is the code we used in Chapter 3 to choose a random word from an array:

randomWords[Math.floor(Math.random() * randomWords.length)];

If we turn this code into a function, we can reuse it to pick a random word from an array without having to enter the same code each time. For example, here’s how we could define a pickRandomWord function.

var pickRandomWord = function (words) {

return words[Math.floor(Math.random() * words.length)];

};

All we’re doing here is wrapping the previous code in a function. Now, we can create this randomWords array . . .

var randomWords = ["Planet", "Worm", "Flower", "Computer"];

and pick a random word from this array using the pickRandomWord function, like this:

pickRandomWord(randomWords);

"Flower"

We can use this same function on any array. For example, here’s how we would pick a random name from an array of names:

pickRandomWord(["Charlie", "Raj", "Nicole", "Kate", "Sandy"]);

"Raj"

A Random Insult Generator

Now let’s try re-creating our random insult generator, using our function that picks random words. First, here’s a reminder of what the code from Chapter 3 looked like:

var randomBodyParts = ["Face", "Nose", "Hair"];

var randomAdjectives = ["Smelly", "Boring", "Stupid"];

var randomWords = ["Fly", "Marmot", "Stick", "Monkey", "Rat"];

// Pick a random body part from the randomBodyParts array:

var randomBodyPart = randomBodyParts[Math.floor(Math.random() * 3)];

// Pick a random adjective from the randomAdjectives array:

var randomAdjective = randomAdjectives[Math.floor(Math.random() * 3)];

// Pick a random word from the randomWords array:

var randomWord = randomWords[Math.floor(Math.random() * 5)];

// Join all the random strings into a sentence:

var randomString = "Your " + randomBodyPart + " is like a " +

randomAdjective + " " + randomWord + "!!!";

randomString;

"Your Nose is like a Stupid Marmot!!!"

Notice that we end up repeating words[Math.floor(Math.random() * length)] quite a few times in this code. Using our pickRandomWord function, we could rewrite the program like this:

var randomBodyParts = ["Face", "Nose", "Hair"];

var randomAdjectives = ["Smelly", "Boring", "Stupid"];

var randomWords = ["Fly", "Marmot", "Stick", "Monkey", "Rat"];

// Join all the random strings into a sentence:

var randomString = "Your " + pickRandomWord(randomBodyParts) +

" is like a " + pickRandomWord(randomAdjectives) +

" " + pickRandomWord(randomWords) + "!!!";

randomString;

"Your Nose is like a Smelly Marmot!!!"

image with no caption

There are two changes here. First, we use the pickRandomWord function when we need a random word from an array, instead of using words[Math.floor(Math.random() * length)] each time. Also, instead of saving each random word in a variable before adding it to the final string, we’re adding the return values from the function calls directly together to form the string. A call to a function can be treated as the value that the function returns. So really, all we’re doing here is adding together strings. As you can see, this version of the program is a lot easier to read, and it was easier to write too, since we reused some code by using a function.

Making the Random Insult Generator into a Function

We can take our random insult generator one step further by creating a larger function that produces random insults. Let’s take a look:

generateRandomInsult = function () {

var randomBodyParts = ["Face", "Nose", "Hair"];

var randomAdjectives = ["Smelly", "Boring", "Stupid"];

var randomWords = ["Fly", "Marmot", "Stick", "Monkey", "Rat"];

// Join all the random strings into a sentence:

var randomString = "Your " + pickRandomWord(randomBodyParts) +

" is like a " + pickRandomWord(randomAdjectives) +

" " + pickRandomWord(randomWords) + "!!!";

➊ return randomString;

};

generateRandomInsult();

"Your Face is like a Smelly Stick!!!"

generateRandomInsult();

"Your Hair is like a Boring Stick!!!"

generateRandomInsult();

"Your Face is like a Stupid Fly!!!"

Our new generateRandomInsult function is just the code from before placed inside a function with no arguments. The only addition is at ➊, where we have the function return randomString at the end. You can see a few sample runs of the preceding function, and it returns a new insult string each time.

Having the code in one function means we can keep calling that function to get a random insult, instead of having to copy and paste the same code every time we want a new insult.

Leaving a Function Early with return

As soon as the JavaScript interpreter reaches return in a function, it leaves the function, even if more code remains in the function body.

One common way to use return is to leave a function early if any of the arguments to the function are invalid; that is, if they’re not the kind of arguments the function needs in order to run properly. For example, the following function returns a string telling you the fifth character of your name. If the name passed to the function has fewer than five characters, the function uses return to leave the function immediately. This means the return statement at the end, which tells you the fifth letter of your name, is never executed.

image with no caption

var fifthLetter = function (name) {

➊ if (name.length < 5) {

➋ return;

}

return "The fifth letter of your name is " + name[4] + ".";

};

At ➊ we check to see whether the length of the input name is less than five. If it is, we use return at ➋ to exit the function early.

Let’s try calling this function.

fifthLetter("Nicholas");

"The fifth letter of your name is o."

The name Nicholas is longer than five characters, so fifthLetter completes and returns the fifth letter in the name Nicholas, which is the letter o. Let’s try calling it again on a shorter name:

fifthLetter("Nick");

undefined

When we call fifthLetter with the name Nick, the function knows that the name isn’t long enough, so it exits early with the first return statement at ➋. Because there is no value specified after the return at ➋, the function returns undefined.

Using return Multiple Times Instead of if...else Statements

We can use multiple return keywords inside different if statements in a function body to have a function return a different value depending on the input. For example, say you’re writing a game that awards players medals based on their score. A score of 3 or below is a bronze medal, scores between 3 and 7 are silver, and anything above 7 is gold. You could use a function like medalForScore to evaluate a score and return the right kind of medal, as shown here:

image with no caption

var medalForScore = function (score) {

if (score < 3) {

➊ return "Bronze";

}

➋ if (score < 7) {

return "Silver";

}

➌ return "Gold";

};

At ➊ we return "Bronze" and exit the function if the score is less than 3. If we reach ➋ we know that score must be at least 3, because if it was less than 3, we would have returned already (that is, we would have exited the function when we reached the return keyword in the first test). Finally, if we reach ➌, we know that score must be at least 7, so there’s nothing left to check, and we can just return "Gold".

Although we’re checking multiple conditions, we don’t need to use chained if...else statements. We use if...else statements to ensure that only one of the options is executed. When each of the options has its own return statement, this also ensures that only one of the options will be executed (because functions can return only once).

SHORTHAND FOR CREATING FUNCTIONS

There’s a longhand way and a shorthand way to write functions. I’m using the longhand way because it shows more clearly how a function is stored as a variable. Still, you should know what the shorthand looks like because lots of JavaScript code uses it. Once you’re used to how functions work, you might want to use the shorthand version, too.

Here’s an example of a longhand function:

var double = function (number) {

return number * 2;

};

The shorthand version looks like this:

function double(number) {

return number * 2;

}

As you can see, in the longhand version, we explicitly create a variable name and assign the function to the variable, so double appears before the function keyword. By contrast, the function keyword appears first in the shorthand version, followed by the function name. In this version, the variable double is created by JavaScript behind the scenes.

In technical terms, the longhand version is known as a function expression. The shorthand version is known as a function declaration.

What You Learned

Functions allow us to reuse blocks of code. They can do different things depending on the arguments passed to them, and they can return values to the location in the code where the function was called. Functions also make it possible to give a piece of code a meaningful name. For example, the name of the function pickRandomWord makes clear that the function has something to do with picking a random word.

In the next chapter, we’ll learn how to write JavaScript that can manipulate HTML documents.

Programming Challenges

Here are some challenges for you to practice working with functions.

#1: DOING ARITHMETIC WITH FUNCTIONS

Create two functions, add and multiply. Each should take two arguments. The add function should sum its arguments and return the result, and multiply should multiply its arguments.

Using only these two functions, solve this simple mathematical problem:

36325 * 9824 + 777

#2: ARE THESE ARRAYS THE SAME?

Write a function called areArraysSame that takes two arrays of numbers as arguments. It should return true if the two arrays are the same (that is, they have the same numbers in the same order) and false if they’re different. Try running the following code to make sure your functions are working correctly:

areArraysSame([1, 2, 3], [4, 5, 6]);

false

areArraysSame([1, 2, 3], [1, 2, 3]);

true

areArraysSame([1, 2, 3], [1, 2, 3, 4]);

false

Hint 1: you’ll need to use a for loop to go through each of the values in the first array to see whether they’re the same in the second array. You can return false in the for loop if you find a value that’s not equal.

Hint 2: you can leave the function early and skip the for loop altogether if the arrays are different lengths.

#3: HANGMAN, USING FUNCTIONS

Go back to your Hangman game from Chapter 7. We’re going to rewrite it using functions.

I’ve rewritten the final Hangman code here, but with certain parts of the code replaced by function calls. All you need to do is write the functions!

// Write your functions here

var word = pickWord();

var answerArray = setupAnswerArray(word);

var remainingLetters = word.length;

while (remainingLetters > 0) {

showPlayerProgress(answerArray);

var guess = getGuess();

if (guess === null) {

break;

} else if (guess.length !== 1) {

alert("Please enter a single letter.");

} else {

var correctGuesses = updateGameState(guess, word, answerArray);

remainingLetters -= correctGuesses;

}

}

showAnswerAndCongratulatePlayer(answerArray);

This version of the code using functions is almost as simple as the pseudocode version from Chapter 7. This should give you some idea of how useful functions can be for making code easier to understand.

Here are the functions you need to fill in:

var pickWord = function () {

// Return a random word

};

var setupAnswerArray = function (word) {

// Return the answer array

};

var showPlayerProgress = function (answerArray) {

// Use alert to show the player their progress

};

var getGuess = function () {

// Use prompt to get a guess

};

var updateGameState = function (guess, word, answerArray) {

// Update answerArray and return a number showing how many

// times the guess appears in the word so remainingLetters

// can be updated

};

var showAnswerAndCongratulatePlayer = function (answerArray) {

// Use alert to show the answer and congratulate the player

};