Section 2 · Logic and Functions
Functions: Declarations, Arrows and Defaults
19 min4 min readCode playground
Lesson at a glance
Write your own functions as declarations and arrow functions, pass arguments in and get results out with return, give parameters default values, and pass functions to other functions.
- 1Declaring and calling a function
- 2Default parameters
- 3Arrow functions
- 4Functions are values
- 5Small, pure functions
No video here — just the real thing: a written lesson, runnable examples, a quiz and practice.
In the last two lessons you filled in function bodies that were written for you. Now you write your own. A function is a named, reusable piece of a program: you write the steps once and run them whenever you need, with different inputs. Pocket formats money in a dozen places; without functions you would copy (cents / 100).toFixed(2) into every one, and fix every copy when the format changes.
Declaring and calling a function
function formatMoney(cents) {
const dollars = (cents / 100).toFixed(2);
return `${dollars}`;
}
console.log(formatMoney(1220));
console.log(formatMoney(450));The first five lines are a function declaration. They do not run anything; they create a function named formatMoney and remember its steps. cents is a parameter, a name for an input that does not have a value yet.
formatMoney(1220) is a call. The value in the parentheses, 1220, is an argument. When the engine reaches the call, it pauses the current line, jumps into the function with cents pointing at 1220, runs the body, and comes back when it hits return. The call expression is then replaced by the returned value, "$12.20", which console.log prints.
A function can have several parameters, separated by commas, and the arguments are matched by position: the first argument goes to the first parameter, and so on.
return does two things: it decides the result, and it ends the function on the spot. Any line after a return in the same block never runs. If a function finishes without reaching a return, the call evaluates to undefined.
Default parameters
If you call a function with fewer arguments than parameters, the missing ones are undefined. A default parameter gives them a sensible value instead:
function formatMoney(cents, symbol = "$") {
return `${symbol}${(cents / 100).toFixed(2)}`;
}
console.log(formatMoney(1220));
console.log(formatMoney(1220, "€"));The default is used when the argument is missing or undefined, and only then. Passing 0, "" or null counts as a real argument.
Arrow functions
There is a second, shorter way to write functions, the arrow function. It is a value, so you store it in a const:
const toCents = (dollars) => Math.round(dollars * 100);
const isBig = (cents) => cents >= 10000;
console.log(toCents(12.2), isBig(toCents(120)));When the body is a single expression, as here, you leave out the braces and the return: the expression’s value is returned automatically. When you need several statements, use braces, and then return is required again:
const budgetLeft = (budget, spent) => {
const left = budget - spent;
return left > 0 ? left : 0;
};
console.log(budgetLeft(2000, 2200));Which style should you use? Both are everywhere in real code. A common default, and the one this course follows: declarations for named, top-level functions, arrows for short functions passed to other functions. One practical difference: declarations are hoisted, which means you can call them on a line above where they are written. A const arrow function only exists once its line has run.
Functions are values
In JavaScript a function is a value like a number or a string. You can store it, and you can pass it to another function as an argument. That is the idea behind much of modern JavaScript:
function applyToAll(amounts, transform) {
const results = [];
for (const amount of amounts) {
results.push(transform(amount));
}
return results;
}
const formatMoney = (cents) => `${(cents / 100).toFixed(2)}`;
console.log(applyToAll([450, 1220], formatMoney));
console.log(applyToAll([450, 1220], (c) => c * 2));applyToAll does not know or care what transform does; it calls it once per item and collects the results with push, which adds an item to the end of an array. A function passed in like this is called a callback. Notice that you pass formatMoney without parentheses: you are handing over the function, not calling it. Arrays have this exact helper built in, called map, and section 3 puts it to work.
Small, pure functions
Notice what every helper in this lesson has in common: it uses only its parameters, returns a result, and changes nothing outside itself. A function like that is called pure. Give it the same arguments and it returns the same answer every time, so you can test it with one line, reuse it anywhere, and trust it without reading its body again.
Not every function can be pure. Something eventually has to print to the screen or save data. The habit that keeps programs manageable is to do the calculating in small pure functions and keep the printing and saving in a few clearly named places. Pocket follows that split all the way to the final app.
Functions create their own little world of names inside them. How that world relates to the code around it is called scope, and it is the subject of the next lesson.
Key takeaways
- A function packages steps under a name; parameters are the inputs it declares, arguments are the values you pass when you call it.
returnends the function and hands a value back; a function withoutreturngives backundefined.- Arrow functions (
(x) => x * 2) are a shorter syntax; with curly braces they need an explicitreturn. - Default parameters (
symbol = \"$\") apply when an argument is missing orundefined. - Functions are values, so you can store them in variables and pass them to other functions.