JavaScript Rest Parameters - Exercise 2
A rest parameter gathers all numeric arguments into an array, so the function can calculate the total and divide by the number of values. With no arguments, the example returns NaN because there is no meaningful average.
// How can a rest parameter calculate an average?
function average(...numbers) {
return numbers.length === 0 ? NaN : numbers.reduce((total, number) => total + number, 0) / numbers.length;
}
console.log(average(10, 20, 30)); // 20Put required or specially named values before the rest parameter. The rest parameter then collects every remaining argument into an array that can be processed normally.
// How can a named first argument be combined with rest values?
function greet(greeting, ...names) {
return names.map(name => `${greeting}, ${name}!`);
}
console.log(greet('Hello', 'Ada', 'Lin')); // ['Hello, Ada!', 'Hello, Lin!']An empty rest array means that the caller supplied no arguments after the named parameters. It is still a real array, so length checks and array methods work normally.
// What does an empty rest array indicate?
function countExtra(first, ...rest) {
return rest.length;
}
console.log(countExtra('only')); // 0A logging helper can accept any number of values without using the older arguments object. Rest gives the helper a named array that can be forwarded to console.log.
// How can rest parameters improve a logging helper?
function logWithLabel(label, ...values) {
console.log(`[${label}]`, ...values);
}
logWithLabel('debug', 'loaded', 3);The rest parameter must be last because it collects every argument that remains. A later parameter would have no reliable way to receive a value, so JavaScript rejects that parameter list.
// Why must a rest parameter be last?
function collect(first, ...rest) {
return [first, rest];
}
console.log(collect('a', 'b', 'c')); // ['a', ['b', 'c']]
// function invalid(...rest, last) {} // SyntaxErrorRest values are stored in an array, so pass them to another function with spread syntax. Spread expands the array into separate positional arguments at the call site.
// How can rest values be passed to another function?
function add(first, second, third) {
return first + second + third;
}
function addAll(...numbers) {
return add(...numbers);
}
console.log(addAll(2, 3, 4)); // 9Array rest collects values after the skipped positions. Use empty slots for the first two elements, then place the rest pattern last.
// How can array rest skip the first two values?
const scores = [10, 20, 30, 40];
const [, , ...remainingScores] = scores;
console.log(remainingScores); // [30, 40]Object rest copies the remaining own enumerable properties into a new object after the named properties are removed from the pattern. It does not mutate the original object.
// What does object rest preserve during destructuring?
const user = { id: 7, name: 'Ada', role: 'admin' };
const { id, ...details } = user;
console.log(id, details); // 7 { name: 'Ada', role: 'admin' }Destructure the sensitive property into a variable and use object rest to build a sanitized copy. The original object still contains the property, so this pattern does not erase or secure the secret by itself.
// How can rest syntax omit a sensitive property?
const account = { username: 'ada', password: 'hidden', role: 'admin' };
const { password, ...safeAccount } = account;
console.log(safeAccount); // { username: 'ada', role: 'admin' }A variadic formatter can accept a format string and any number of replacement values. The rest array makes those values easy to validate or transform before returning the formatted result.
// How can a rest parameter support a variadic formatter?
function formatList(separator, ...items) {
return items.join(separator);
}
console.log(formatList(' | ', 'red', 'green', 'blue')); // red | green | blue