1. Functions: naming a piece of work
Every interpreter, compiler and engine in this book is built out of one humble idea: give a piece of work a name, then use it as often as you like.
- Write a function with parameters and a return value, and call it.
- Explain the difference between a parameter and an argument.
- Predict what a function returns, including when it returns nothing.
- Explain why variables made inside a function vanish when it finishes.
Same work, written twice
You already know enough JavaScript to get real work done. Say you’re working out the area of two rectangles:
const w1 = 3;
const h1 = 4;
console.log(w1 * h1); // 12
const w2 = 5;
const h2 = 2;
console.log(w2 * h2); // 10
That works. But look at what’s going on: the idea “multiply width by height” appears twice, glued to particular numbers each time. If you had a hundred rectangles you’d write it a hundred times. And if you got it wrong (say you meant to add a border first), you’d have to fix it in a hundred places.
What you really want is to write the idea down once, give it a name, and then just say the name.
A function is a recipe card. You write the steps once (“multiply the width
by the height”), give the card a title (area), and put it on the shelf.
Whenever you need an area, you don’t rewrite the recipe. You say “do
area, with these numbers”, and you get the answer back.
A machine with a slot and a chute
Here is the picture to keep in your head. A function is a little machine. You drop a value in the top. The machine does its work. A value comes out of the bottom.
In code, that machine looks like this:
function double(n) {
return n * 2;
}
console.log(double(3)); // 6
console.log(double(10)); // 20
Read it out loud: “function double, taking n: return n times two.” The
first three lines define the function: they build the machine and put
it on the shelf. Nothing is computed yet. The console.log lines
call it: each double(...) runs the machine once.
A function is a named block of code that can be run on demand. You
call it by writing its name followed by parentheses: double(3).
Inside the parentheses go the arguments: the values you hand it.
In the definition, the names in parentheses (n) are the
parameters: the names the function uses for whatever it was handed.
People mix up parameter and argument all the time, so here’s the trick
for keeping them apart. The parameter is the placeholder name,
written once in the definition. The argument is the actual
value, and it can be different on every call. In double(3), the
argument is 3 and the parameter n holds it for the length of that call.
Try it. Change the numbers, call double a few more times, or make a
triple function of your own.
function double(n) {
return n * 2;
}
console.log(double(3));
console.log(double(10));
console.log(double(3) + 1);Getting a value back out: return
The word return does two jobs at once:
- It decides what value comes out of the call. The call
double(3)becomes6, as if you’d typed6there yourself. That’s why you can use a call anywhere you could use a value:double(3) + 1is7. - It stops the function immediately. Any lines after a
returnthat runs are skipped.
The second job makes return handy inside an if:
function sign(x) {
if (x < 0) {
return 'negative';
}
if (x === 0) {
return 'zero';
}
return 'positive';
}
console.log(sign(-5)); // negative
console.log(sign(7)); // positive
When x is -5, the first return runs and the function is finished.
The other two checks never happen.
What if a function never reaches a return? Then the call still produces
a value: the special value undefined, which is JavaScript’s way of
saying “nothing”.
function greet(name) {
console.log('Hello, ' + name);
}
const result = greet('Ada');
console.log(result); // undefined
greet prints something, but it doesn’t return anything. Printing and
returning are different things, and mixing them up is one of the most common
beginner bugs. Printing shows a value to a human. Returning hands a value
back to the code that made the call, so that code can keep working with it.
console.log inside a function does not give the value back to the caller.
If you write const a = double(3); and double only prints 6, then
a is undefined. If the caller needs the value, return it.
Each call gets a fresh page
Here is the idea that matters most later in the book. Every time you call
a function, JavaScript gives that call its own fresh, private page to
write on. The parameters are written on it first, holding the arguments.
Any variables the body creates with let or const go on that page too.
They are called local variables.
When the call finishes, the page is thrown away. Only the returned value survives. Step through it:
function area(w, h) {const a = w * h;return a;}const r = area(3, 4);console.log(r);
That’s why this doesn’t work:
function area(w, h) {
const a = w * h;
return a;
}
area(3, 4);
console.log(a);
// ReferenceError: a is not defined
a existed only on the page for that one call, and that page is gone. The
outside code never sees it. This is a good thing: two functions can both
use a variable called a without stepping on each other, because each call
writes on its own page.
That “fresh page per call” really exists inside every JavaScript engine, and you’ll build one yourself. In Part III, our interpreter keeps an environment for each call: literally a little table of names and values. In Part IV, the virtual machine keeps them in a stack frame. In Part VII, you’ll see why it matters to Viscosity whether a value can escape its page, because values that never escape can be stored however we like.
Functions that use functions
Once a piece of work has a name, other functions can use it. That’s how big programs get built: small, named, trustworthy pieces, stacked up.
function square(x) {
return x * x;
}
function hypot(a, b) {
return Math.sqrt(square(a) + square(b));
}
console.log(hypot(3, 4)); // 5
hypot calls square twice, and each of those calls gets its own page
(with its own x). Math.sqrt is a function too: it’s built into
JavaScript, and you call it exactly the same way.
Every program in this book, from a 50-line calculator to Viscosity itself, is just this idea repeated: name a piece of work, then build bigger work out of named pieces. Crafting Interpreters, the book this one borrows its shape from, builds a whole programming language this way, one small function at a time[3].
Your turn
Each exercise has tests that check your function, hints if you get stuck, and a full worked solution. Try for a few minutes before peeking: the struggle is where the learning happens. The second one is extra practice: do it if you have time, or come back to it later.
Write a function average(a, b) that returns the average of its two arguments. For example average(2, 4) should return 3.
function average(a, b) {
// your code here
}
console.log(average(2, 4));Write clamp(x, lo, hi): it returns lo if x is below lo, returns hi if x is above hi, and otherwise returns x unchanged. Games use this all the time, for example to keep a player inside the screen.
function clamp(x, lo, hi) {
// your code here
}
console.log(clamp(15, 0, 10));What you learned
- A function names a piece of work. Defining it puts it on the shelf.
Calling it (
name(args)) runs it. - Parameters are the placeholder names in the definition. Arguments are the actual values in a call.
returnsends a value back and stops the function. With noreturn, a call producesundefined.- Printing is not returning.
- Each call gets a fresh page for its local variables, and the page is thrown away when the call ends.
Next, you’ll meet the first way of holding many values at once: arrays.
Check your understanding
0/6- 1.
What does this print?
function f(n) { return n + 1; } console.log(f(f(1))); - 2.
In
function greet(name) { ... }called asgreet('Ada'), what is'Ada'? - 3.
What does this print?
function g(x) { if (x > 0) { return 'yes'; } return 'no'; console.log('done'); } console.log(g(5)); - 4.
A function prints a number with
console.logbut has noreturn. You writeconst r = f();. What isr? - 5.
Why can two different functions both have a local variable called
totalwithout any conflict? - 6.
Which line calls a function (rather than defining it)?
References
- [1] MDN contributors. Functions (JavaScript Guide). MDN Web Docs. developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions (checked 2026-10-31)
- [2] MDN contributors. console: log() static method. MDN Web Docs. developer.mozilla.org/en-US/docs/Web/API/console/log_static (checked 2026-10-31)
- [3] Robert Nystrom (2021). Crafting Interpreters. Free web edition at craftinginterpreters.com (© 2015–2021); source, text and test suite at github.com/munificent/craftinginterpreters. github.com/munificent/craftinginterpreters (checked 2026-10-31)