Function Expressions and Arrow Functions
A function can be stored in a variable like any other value, arrow functions (=>) write small functions in a line, and default values fill in the arguments a caller leaves out.
Apprentice · JavaScript · Updated
After this lesson you can
- Write a function as a function expression or an arrow function, with or without braces
- Give a parameter a default value and predict which value the function uses
Key takeaways
- A function expression stores a function in a variable, such as const shout = function (message) { ... };, and you call it by the variable's name.
- An arrow function is a shorter way to write one, (parameters) => { body }. The => is read "arrow".
- With no braces after the arrow, an arrow function returns the value of its one expression by itself. With braces, it needs return, or it gives back undefined.
- A default value, as in lives = 3, is used when the caller leaves that argument out.
Open almost any JavaScript code written in the last few years, a tutorial, a project on GitHub, the code behind a website, and you'll see lines like score => score * 2 everywhere. Those are arrow functions, the short way to write a function, and you'll read and write more of them than any other kind. In Module 2 you'll hand small arrow functions to whole lists of data, to pick out the high scores or total up a playlist.
This lesson shows two more ways to write the functions you already know: storing a function in a variable, and the arrow form. It ends with default values, for the arguments a caller doesn't hand over.
A function is a value
You save a friend's phone number in your contacts under their name, and from then on you call them by tapping the name. A function can be saved under a name the same way: in a variable, like a number or a string.
A function written as a value and stored in a variable is called a function expression:
const shout = function (message) {
return message.toUpperCase() + '!';
};
console.log(shout('game over'));
console.log(shout('new high score'));
GAME OVER!
NEW HIGH SCORE!
It works like the function declarations you've written, with three differences in the way it's written:
- It starts with
constand a name, and= functioncomes after the name. - The
functionkeyword has no name of its own. The variable's name,shout, is how you call it. - It ends with a semicolon after the closing
}, because the whole thing is oneconststatement, the same asconst lives = 3;.
You call it the same way as any function: the name, then the arguments in parentheses.
Arrow functions: the short way
An arrow function is a function expression with less to type. Leave out the word function, and put => after the parentheses. The => is read "arrow": an equals sign and a greater-than sign together, pointing from the parameters to the body.
const starPoints = (stars) => {
return stars * 100;
};
console.log(starPoints(3));
console.log(starPoints(7));
300
700
This does exactly what the function expression form does. Watch the order of the two characters: => is the arrow, and >= (greater than or equal to) is a comparison. Swap them and JavaScript reads something else entirely.
The short form: an implied return
When the body is one expression that works out a value, an arrow function can be shorter still. Leave out the curly braces and the word return, and the arrow function hands back the value of that expression by itself. That's called an implied return (some books call it an implicit return, or a concise body):
const starPoints = (stars) => stars * 100;
const isWinner = (score) => score >= 1000;
const gameTitle = () => 'Coin Dash';
console.log(starPoints(3));
console.log(isWinner(1250));
console.log(gameTitle());
300
true
Coin Dash
Three things to notice about the parameters:
- One parameter can go without its parentheses:
stars => stars * 100works too. - No parameters still need empty parentheses:
() => 'Coin Dash'. - Two or more need parentheses around them:
(coins, gems) => coins * 10 + gems * 50.
The one trap: braces mean a block, and a block needs return. Here the braces are back, but the return isn't:
const starPoints = (stars) => { stars * 100; };
console.log(starPoints(3));
undefined
Try it. Make a file named arrows.js. Write const double = (points) => points * 2; and print double(450). Then write the same function three more ways: with braces and return, as a function expression, and as a function declaration. Print double(450) with each one: all four print 900.
Default parameter values
At a coffee shop, a drink comes in medium unless you ask for another size. A function can do the same for its parameters: give one a default value, and the function uses it whenever the caller leaves that argument out.
Write the default with = right after the parameter's name:
const startGame = (playerName, lives = 3) => {
return `${playerName} starts with ${lives} lives`;
};
console.log(startGame('RocketRae'));
console.log(startGame('PixelPanda', 5));
console.log(startGame('Max', undefined));
console.log(startGame('Jo', 0));
RocketRae starts with 3 lives
PixelPanda starts with 5 lives
Max starts with 3 lives
Jo starts with 0 lives
The default fills in only when the argument is missing, or is undefined. Any value you hand over wins, even 0: Jo really does start with no lives.
Put parameters with defaults after the ones without, as lives = 3 comes after playerName. Arguments still fill parameters in order, so a default at the end is the one a caller can leave out. Defaults work in function declarations too: function startGame(playerName, lives = 3) { ... }.
Which one should you write?
All three forms make a function that you call the same way. They differ in where they're used most:
| Form | Looks like | Good for |
|---|---|---|
| Function declaration | function showTitle() { ... } |
The main named steps of your program |
| Arrow function, short form | (stars) => stars * 100 |
A small calculation that fits in one line |
| Arrow function with braces | (stars) => { ... return ...; } |
A small function that needs a few lines |
The function expression with the function keyword is the oldest of the three. You'll still see it in older code and tutorials, so it's worth recognizing, but new code usually uses an arrow function instead.
Check yourself
2 questions to try on the lesson page.
So what
You can now read the three ways JavaScript code writes a function, and write the short arrow form that modern code is full of. In Module 2 you'll hand arrow functions to whole lists, and a line such as scores.filter((score) => score > 1000) will pick out every high score at once.