Topic 04

Functions

JavaScriptHands-on

Some work gets done again and again: format a price, build a greeting, check a field. Writing the same lines each time makes a program long, and every fix turns into a hunt for all the copies. A function is a named piece of work you can run whenever you need it, with different inputs each time. Functions keep programs short, and in a browser they are also how you tell the page what to do when something happens, which is the whole of Chapter 9.

A function is like a recipe card with blanks on it: "bake at so many degrees for so many minutes". You write the card once. Each time you use it, you fill in the blanks, follow the steps, and get a cake back. Writing the card bakes nothing; only using it does.

Declaring and Calling a Function

To declare a function is to write it down: the keyword function, a name, round brackets holding its parameters, and a block in curly braces holding the work. Parameters are names for the inputs, the blanks on the card. The function below takes an amount and a currency and gives back the price as text.

js/main.js
function formatPrice(amount, currency) {
  return `${amount.toFixed(2)} ${currency}`;
}

console.log(formatPrice(4.5, "EUR"));
console.log(formatPrice(12, "USD"));
Console output
4.50 EUR
12.00 USD

Inside the function, toFixed writes a number as text with exactly two digits after the decimal point. A function that belongs to a value like this is called a method, and you reach it with a dot after the value. The template literal then puts the currency after the amount, with a space between.

Declaring the function runs none of it. The work happens when you call it: its name, followed by round brackets holding the values to use, which are called arguments. The arguments fill the parameters in order, so in the first call four and a half becomes the amount and EUR becomes the currency. The two calls give two answers from one piece of code: 4.50 EUR and 12.00 USD.

return or console.log?

The keyword return hands a value back to whoever called the function, and the function stops there. The call itself then stands for that value: you can store it under a name, pass it to another function, or put it inside a template literal. In the block above, the returned text was passed straight to console.log.

The classic beginner mix-up is to log the result inside the function instead of returning it. It looks as if it works, because the text appears in the Console. Watch what the caller receives, though.

js/main.js
function formatPriceLogged(amount, currency) {
  console.log(`${amount.toFixed(2)} ${currency}`);
}

const label = formatPriceLogged(4.5, "EUR");
console.log(`Price: ${label}`);
Console output
4.50 EUR
Price: undefined

The function writes 4.50 EUR in the Console, then finishes without returning anything. A function with no return gives back undefined, so the name label points at nothing, and the second line reads Price: undefined. This is the undefined of the previous topics: nothing was ever set.

The rule that avoids it: a function that makes a value returns it, and the caller decides whether to log it, show it or store it. console.log itself returns nothing, which is why the Console prints undefined under any line you type that only logs something.

Arrow Functions: The Short Form

JavaScript has a second, shorter way to write a function, called an arrow function. You write the parameters in round brackets, then an arrow made of an equals sign and a greater-than sign, then the work. When the work is a single expression, you can leave out both the braces and the word return: the value of the expression is returned automatically. The arrow function is stored under a name with const, like any other value.

js/main.js
const formatPrice = (amount, currency) => `${amount.toFixed(2)} ${currency}`;

console.log(formatPrice(4.5, "EUR"));

This one line does the same job as the three-line version at the top of the page, and the Console again shows 4.50 EUR. If the work needs several lines, put braces around them after the arrow, and then you must write return again, exactly as in the long form. The short form earns its place in Chapter 7, where small functions are handed to other functions. This is a simplification: arrow functions differ from the long form in a few details that this book never relies on, and for the work here they do the same job.

Where Does a Name Live?

A name made with const or let inside a pair of curly braces exists only inside those braces: inside a function, inside an if block, anywhere. The region of code where a name can be used is called its scope. Outside it, the name does not exist.

js/main.js
function makeGreeting(visitor) {
  const greeting = `Hello, ${visitor}!`;
  return greeting;
}

console.log(makeGreeting("Ana"));
console.log(greeting);
Console output
Hello, Ana!
Uncaught ReferenceError: greeting is not defined

The first call works: the function builds Hello, Ana! and returns it. The last line tries to use the name greeting from outside the function, and the Console answers in red: a reference error, saying greeting is not defined. The name was made inside the function and existed only there. The next topic shows how to read an error like this one.

That limit is useful. Two functions can each have a name called total without disturbing each other, because neither can see inside the other. Names made outside every block work the other way: they can be seen, and changed, from everywhere, which is convenient and risky in equal measure. So the habit to build: a function takes what it needs through its parameters, and hands back what it makes with return. A function like that is quick to check, because you can call it with known inputs and look at what comes back.

A function: inputs in, one value out
Inputsprice and currency
→
The workformat with two decimals
→
Returnedthe text 4.50 EUR
Common Confusions
  • "console.log returns the value it shows." It shows the value in the Console and returns nothing. A function that only logs its result gives its caller undefined.
  • "Arrow functions are a different kind of thing." For this book they are a shorter way to write the same idea: inputs in, a value out.
  • "A function runs when it is declared." Declaring only writes the recipe down. It runs each time it is called, and not before.
Why It Matters
  • Every event handler, every piece of code that draws the projects and every request for data in this book is a function.
  • Functions that return their result can be reused anywhere and checked on their own, one input at a time.

Knowledge Check

A function logs its result with console.log but has no return. What does the caller receive?

  • The same text that appeared in the Console
  • An error saying that the result is missing
  • The number of characters that were logged
  • The value undefined, which means nothing at all

When does the work inside a function run?

  • As soon as the browser reads the declaration
  • Once, when the visitor closes the page
  • Every few seconds while the page stays open
  • Each time the function is called by its name

A name is made with const inside a function's braces. Where can it be used?

  • Only inside that function's own pair of curly braces
  • Anywhere in the same file, after the function
  • Anywhere, once the function has been called
  • In the Console, but not in other functions

What does const next = (n) => n + 1; give back when called as next(5)?

  • undefined, because there is no return
  • The text n + 1, since it is never run
  • 6, the value of n with 1 added to it
  • 5, the value that was passed in

You got correct