Warm-up · Activity 1 of 7
// B4.2 · ~30 min · Beginner
Default and rest parameters
After this lesson you know what a parameter holds when its argument is missing, give it a default value, and collect any number of arguments into an array.
You will be able to
- Predict what a parameter holds when its argument is missing, and give it a default value
- Know which arguments use the default: a missing one or undefined, but not null, 0 or ""
- Collect any number of arguments into a real array with a rest parameter, ...items
Predict · Activity 2 of 7
Predict before you read on: what does this print?
function greet(name = "friend") { return "Hello, " + name; } console.log(greet(), "|", greet(null));Practice · Activity 3 of 7
Give factor a default of 2, so that scale(5) gives 10 and scale(5, 3) gives 15.
function scale(value, factor____) { return value * factor; } console.log(scale(5), scale(5, 3));function scale(value, factor) {Practice · Activity 4 of 7
function show(a = "default") { return a; }. Match each call to what console.log prints for it.
Practice · Activity 5 of 7
What does this print?
function count(first, ...others) { return others.length; } console.log(count("a", "b", "c", "d"));Brain teaser · Activity 6 of 7
Brain teaser. total adds up its arguments. It is called once with an array and once with the array spread out. What does this print?
function total(...prices) { let sum = 0; for (const p of prices) { sum += p; } return sum; } const basket = [4, 6, 10]; console.log(total(basket), total(...basket));Apply · Activity 7 of 7
Mini-task. Write receipt(customer, ...prices) with a default of "guest" for customer. It adds up the prices and returns a line such as Ada paid 12.5 EUR for 3 item(s). Call it with a name and three prices, with undefined and one price, and with a name and no prices at all.
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 pizza order line
orderLine takes a pizza, a size with the default "medium", and any number of toppings in a rest parameter. Watch the four calls: one leaves the size out, one passes it, one passes undefined to keep the default while adding toppings, and one passes null. The last line shows that a rest parameter is an array, even an empty one. Run it, then add a fifth call of your own.
main.js
// A pizza order line: a default size and any number of toppings.
function orderLine(pizza, size = "medium", ...toppings) {
let line = size + " " + pizza;
for (const t of toppings) {
line += " + " + t;
}
return line;
}
function toppingsOf(...toppings) {
return toppings;
}
console.log(orderLine("margherita"));
console.log(orderLine("margherita", "large"));
console.log(orderLine("funghi", undefined, "olives", "chili"));
console.log(orderLine("funghi", null));
console.log(toppingsOf("ham", "basil"), toppingsOf().length);
Run it with
node main.jsOutput
medium margherita
large margherita
medium funghi + olives + chili
null funghi
[ 'ham', 'basil' ] 0- A missing size and an undefined size both give the default, medium.
- null is a value, so the default is not used and the line starts with null.
- toppings is an array: with no toppings it is empty, and the for...of loop does not run.
- toppingsOf() with no arguments returns an empty array, whose length is 0.
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
A greeting with defaults
greet(name, greeting) should return a line such as Hi, Ada!. Give name the default "guest" and greeting the default "Hello", so that greet() returns Hello, guest! and greet(undefined, "Hey") returns Hey, guest!. Use defaults in the parameter list, not an if in the body.
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: greet() returns undefined, undefined!, because both parameters are missing.
Hint 2
A default goes right after the parameter name: name = "guest".
Hint 3
Write both: function greet(name = "guest", greeting = "Hello").
Show a solution
One way to solve it. Yours can look different and still pass the checks.
export function greet(name = "guest", greeting = "Hello") {
return greeting + ", " + name + "!";
}
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 greet(name, greeting) {
return greeting + ", " + name + "!";
}
main.test.js
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {greet} from './main.js';
test('greet() uses both defaults', () => {
assert.equal(greet(), 'Hello, guest!', `greet() returned ${JSON.stringify(greet())}, expected "Hello, guest!"`);
});
test('greet("Ada") keeps the default greeting', () => {
assert.equal(greet('Ada'), 'Hello, Ada!', `greet("Ada") returned ${JSON.stringify(greet('Ada'))}, expected "Hello, Ada!"`);
});
test('greet("Ada", "Hi") uses both arguments', () => {
assert.equal(greet('Ada', 'Hi'), 'Hi, Ada!', `greet("Ada", "Hi") returned ${JSON.stringify(greet('Ada', 'Hi'))}, expected "Hi, Ada!"`);
});
test('undefined as the name gives the default', () => {
assert.equal(greet(undefined, 'Hey'), 'Hey, guest!', `greet(undefined, "Hey") returned ${JSON.stringify(greet(undefined, 'Hey'))}, expected "Hey, guest!"`);
});
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
The average of any count
average should take any number of numbers as separate arguments, average(2, 4, 6), and return their average: 4. With no arguments at all it returns 0 instead of dividing by zero. The starter expects a single array and fails. Change the parameter into a rest parameter and handle the empty case.
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: average(2, 4, 6) passes three arguments, but numbers receives only the 2. A for...of loop over a number fails.
Hint 2
Put three dots in front of the parameter: ...numbers collects every argument into an array.
Hint 3
With no arguments, numbers is an empty array and sum / 0 is NaN. Return numbers.length === 0 ? 0 : sum / numbers.length.
Show a solution
One way to solve it. Yours can look different and still pass the checks.
export function average(...numbers) {
let sum = 0;
for (const n of numbers) {
sum += n;
}
return numbers.length === 0 ? 0 : sum / numbers.length;
}
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 average(numbers) {
let sum = 0;
for (const n of numbers) {
sum += n;
}
return sum / numbers.length;
}
main.test.js
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {average} from './main.js';
test('average(2, 4, 6) is 4', () => {
assert.equal(average(2, 4, 6), 4, `average(2, 4, 6) returned ${average(2, 4, 6)}, expected 4`);
});
test('works with two numbers', () => {
assert.equal(average(1, 2), 1.5, `average(1, 2) returned ${average(1, 2)}, expected 1.5`);
});
test('works with one number', () => {
assert.equal(average(5), 5, `average(5) returned ${average(5)}, expected 5`);
});
test('average() with no numbers is 0', () => {
assert.equal(average(), 0, `average() returned ${average()}, expected 0`);
});
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
Forgetting an argument
function shout(text) {
return text.toUpperCase() + "!";
}
console.log(shout());
What Node.js prints
TypeError: Cannot read properties of undefined (reading 'toUpperCase')Why, and the fix
shout() passes no argument, so text is undefined, and undefined has no methods. The message names the method that was looked up on undefined. Pass the argument, shout("hi"), or give the parameter a default: function shout(text = "") { … }.
Expecting null to use the default
function greet(name = "guest") {
return "Hello, " + name.toUpperCase();
}
console.log(greet(null));
What Node.js prints
TypeError: Cannot read properties of null (reading 'toUpperCase')Why, and the fix
A default is used only when the argument is missing or undefined. null was passed on purpose, so name is null and has no toUpperCase. If a caller may pass null, call greet(undefined) instead, or check for null in the body before using the value.
A rest parameter that is not last
function order(...items, customer) {
return customer + ": " + items.length;
}
console.log(order("tea", "cake", "Ada"));
What Node.js prints
SyntaxError: Rest parameter must be last formal parameterWhy, and the fix
A rest parameter takes everything that is left, so nothing can come after it, and the file cannot even be read. Put the single parameters first and the rest parameter last: function order(customer, ...items), and call it as order("Ada", "tea", "cake").
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.