Warm-up · Activity 1 of 7
// B4.3 · ~30 min · Beginner
Return values
After this lesson you return results instead of printing them, stop a function early when its input is bad, and hand back several values at once.
You will be able to
- Return a value from a function and use the call as that value, and tell returning from printing
- Know that a function without return gives undefined, and guard bad input with an early return
- Avoid a line break straight after return, and return an array or object to give back several values
Predict · Activity 2 of 7
Predict before you read on: one function prints, the other returns. What does the program print?
function addLog(a, b) { console.log(a + b); } function addReturn(a, b) { return a + b; } const x = addLog(2, 3); const y = addReturn(2, 3); console.log(x, y);Practice · Activity 3 of 7
Fill in the keyword so that double hands its result back and the program prints 42.
function double(n) { ____ n * 2; } console.log(double(21));n * 2;Practice · Activity 4 of 7
Each return ends the function. What does this print?
function ticketPrice(age) { if (age < 6) { return 0; } if (age < 18) { return 5; } return 9; } console.log(ticketPrice(4), ticketPrice(12), ticketPrice(40));Practice · Activity 5 of 7
Each line is the body of a function. Match it to what console.log prints for a call of that function.
Brain teaser · Activity 6 of 7
Brain teaser. The value is on the next line, nicely indented. What does this print?
function getTotal(a, b) { return a + b; } console.log(getTotal(2, 3));Apply · Activity 7 of 7
Mini-task. Write minMax(numbers) that returns the smallest and the largest number as an array, [low, high]. Guard the empty list first: return [] straight away. Print minMax([7, 2, 9, 4]), minMax([5]) and minMax([]).
Check your work against this list
Build it yourself
Read the worked example, then write the exercises. Your code runs in your browser or on your computer and is never uploaded.
Worked example
A checkout
Four small functions build a receipt. subtotal returns a sum, discount uses early returns as guards, and priceRange returns two values in an array. logLine prints instead of returning: watch what its call gives on the last line. Run it, then change the code to "save5" in the first discount call and predict the new total.
main.js
// Small functions that return values, combined into a receipt.
function subtotal(prices) {
let sum = 0;
for (const p of prices) {
sum += p;
}
return sum;
}
function discount(amount, code) {
if (code !== "SAVE5") {
return 0;
}
if (amount < 20) {
return 0;
}
return 5;
}
function priceRange(prices) {
let low = prices[0];
let high = prices[0];
for (const p of prices) {
if (p < low) {
low = p;
}
if (p > high) {
high = p;
}
}
return [low, high];
}
function logLine(text) {
console.log("> " + text);
}
const prices = [12, 4.5, 20];
const sum = subtotal(prices);
const off = discount(sum, "SAVE5");
console.log("subtotal", sum);
console.log("discount", off, "and with a wrong code", discount(sum, "save5"));
console.log("to pay", (sum - off).toFixed(2));
console.log("range", priceRange(prices));
console.log("logLine gives", logLine("printed, not returned"));
Run it with
node main.jsOutput
subtotal 36.5
discount 5 and with a wrong code 0
to pay 31.50
range [ 4.5, 20 ]
> printed, not returned
logLine gives undefined- The results of subtotal and discount are stored in constants and used again in later lines.
- discount returns 0 as soon as one test fails; return 5 is reached only when both pass.
- priceRange hands back two numbers in one array.
- logLine prints its line first, while its argument is worked out; the call itself is undefined.
Change it and run it
Tab indents and Shift+Tab outdents. To leave the editor with the keyboard, press Esc, then Tab.
The first run downloads the JavaScript runner (up to 0.1 MB) and keeps it cached. Your code runs in your browser’s own engine and stays on your device.
Exercises
Exercise 1 of 2
Return, do not print
fullName(first, last) should return a name such as Ada Lovelace, and initials(first, last) should return initials such as A.L.. The starter prints the right text, but the tests receive undefined. Change both functions so that they return their text instead of printing it.
Tab indents and Shift+Tab outdents. To leave the editor with the keyboard, press Esc, then Tab.
The first run downloads the JavaScript runner (up to 0.1 MB) and keeps it cached. Your code runs in your browser’s own engine and stays on your device.
Hints
Hint 1
Run the tests: the text appears in the output, but each function returns undefined.
Hint 2
console.log shows a value; return hands it to the caller.
Hint 3
Replace console.log( … ) with return …, and drop the closing bracket of console.log.
Show a solution
One way to solve it. Yours can look different and still pass the checks.
// Return the full name, such as "Ada Lovelace".
export function fullName(first, last) {
return first + " " + last;
}
// Return the initials, such as "A.L.".
export function initials(first, last) {
return first[0] + "." + last[0] + ".";
}
Run it on your computer
Install ECMAScript 2026 or newer. Save these files in one folder, open a terminal in that folder, and run the commands below.
main.js
// Return the full name, such as "Ada Lovelace".
export function fullName(first, last) {
console.log(first + " " + last);
}
// Return the initials, such as "A.L.".
export function initials(first, last) {
console.log(first[0] + "." + last[0] + ".");
}
main.test.js
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {fullName, initials} from './main.js';
test('fullName returns the full name', () => {
const got = fullName('Ada', 'Lovelace');
assert.equal(got, 'Ada Lovelace', `fullName("Ada", "Lovelace") returned ${JSON.stringify(got)}, expected "Ada Lovelace"`);
});
test('fullName works for any name', () => {
const got = fullName('Grace', 'Hopper');
assert.equal(got, 'Grace Hopper', `fullName("Grace", "Hopper") returned ${JSON.stringify(got)}, expected "Grace Hopper"`);
});
test('initials returns the initials', () => {
const got = initials('Ada', 'Lovelace');
assert.equal(got, 'A.L.', `initials("Ada", "Lovelace") returned ${JSON.stringify(got)}, expected "A.L."`);
});
package.json
{
"type": "module"
}
package.json tells Node.js that the .js files are modules; keep it in the folder.
Run the program:
node main.jsRun the checks (needs learnrun.js in the same folder):
node --testDownload learnrun.jsExercise 2 of 2
Guard the shipping cost
shippingCost(weight) returns 5 for a parcel up to 2 kg, 9 up to 10 kg and 15 above that. Anything that is not a number above 0 must return "invalid weight". The starter has no guard yet, and one of its returns hands back undefined. Add the guard as an early return at the top and fix the broken return.
Tab indents and Shift+Tab outdents. To leave the editor with the keyboard, press Esc, then Tab.
The first run downloads the JavaScript runner (up to 0.1 MB) and keeps it cached. Your code runs in your browser’s own engine and stays on your device.
Hints
Hint 1
Run the tests: shippingCost(1) returns undefined. Look at the line after the first return.
Hint 2
A line break straight after return ends the statement. Write return 5; on one line.
Hint 3
For the guard, put if (typeof weight !== "number" || weight <= 0) { return "invalid weight"; } as the first lines of the body.
Show a solution
One way to solve it. Yours can look different and still pass the checks.
export function shippingCost(weight) {
// Return "invalid weight" for anything that is not a number above 0.
if (typeof weight !== "number" || weight <= 0) {
return "invalid weight";
}
if (weight <= 2) {
return 5;
}
if (weight <= 10) {
return 9;
}
return 15;
}
Run it on your computer
Install ECMAScript 2026 or newer. Save these files in one folder, open a terminal in that folder, and run the commands below.
main.js
export function shippingCost(weight) {
// Return "invalid weight" for anything that is not a number above 0.
if (weight <= 2) {
return
5;
}
if (weight <= 10) {
return 9;
}
return 15;
}
main.test.js
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {shippingCost} from './main.js';
test('a parcel up to 2 kg costs 5', () => {
assert.equal(shippingCost(1), 5, `shippingCost(1) returned ${JSON.stringify(shippingCost(1))}, expected 5`);
assert.equal(shippingCost(2), 5, `shippingCost(2) returned ${JSON.stringify(shippingCost(2))}, expected 5`);
});
test('a parcel up to 10 kg costs 9', () => {
assert.equal(shippingCost(7), 9, `shippingCost(7) returned ${JSON.stringify(shippingCost(7))}, expected 9`);
});
test('a heavier parcel costs 15', () => {
assert.equal(shippingCost(25), 15, `shippingCost(25) returned ${JSON.stringify(shippingCost(25))}, expected 15`);
});
test('0 and negative weights are invalid', () => {
assert.equal(shippingCost(0), 'invalid weight', `shippingCost(0) returned ${JSON.stringify(shippingCost(0))}, expected "invalid weight"`);
assert.equal(shippingCost(-3), 'invalid weight', `shippingCost(-3) returned ${JSON.stringify(shippingCost(-3))}, expected "invalid weight"`);
});
test('a weight that is not a number is invalid', () => {
assert.equal(shippingCost('3'), 'invalid weight', `shippingCost("3") returned ${JSON.stringify(shippingCost('3'))}, expected "invalid weight"`);
});
package.json
{
"type": "module"
}
package.json tells Node.js that the .js files are modules; keep it in the folder.
Run the program:
node main.jsRun the checks (needs learnrun.js in the same folder):
node --testDownload learnrun.jsCommon mistakes
A line break after return
function total(a, b) {
return
a + b;
}
console.log(total(2, 3).toFixed(2));
What Node.js prints
TypeError: Cannot read properties of undefined (reading 'toFixed')Why, and the fix
JavaScript ends the return statement at the line break, so total returns undefined and a + b never runs. The error appears only later, where the caller uses the result. Keep the value on the return line: return a + b;. A long value can start with an opening bracket on that line: return ( … );.
Printing instead of returning
function greeting(name) {
console.log("Hello, " + name);
}
const text = greeting("Ada");
console.log(text.toUpperCase());
What Node.js prints
TypeError: Cannot read properties of undefined (reading 'toUpperCase')Why, and the fix
greeting prints its line, so the program looks right at first, but it has no return, so text is undefined. Return the value, return "Hello, " + name;, and let the caller print it when it needs to.
return outside a function
const stock = 0;
if (stock === 0) {
console.log("sold out");
return;
}
console.log("in stock");
What Node.js prints
SyntaxError: Illegal return statementWhy, and the fix
return belongs inside a function body. At the top level of a file it is a SyntaxError, so the file cannot be read and not even sold out is printed. Use else for the other branch, or put the code in a function and return from that.
JavaScript in the browser: your browser’s own engine, in a sandboxed worker. Syntax errors are located with acorn 8.18.0, MIT. Licence and source
Exit ticket
5 questions, no hints. Score 80% or more to complete the lesson.
Finish every activity above to unlock the exit ticket.