JavaScript REST Parameters: A Complete Tutorial
Rest parameters collect extra function arguments into a real array. Learn how ...args replaces the arguments object with cleaner, more predictable code.
Rest parameters let a function accept any number of arguments by collecting the extras into a real array. The syntax is three dots before the last parameter name: ...args.
function sum(...numbers) {
return numbers.reduce((total, n) => total + n, 0);
}
console.log(sum(1, 2, 3)); // 6
console.log(sum(10, 20, 30, 40)); // 100No matter how many arguments you pass, they all land in the numbers array. The function handles one or one hundred arguments the same way, with no need to check how many were actually passed.
Rest Parameters vs the arguments Object
Before rest parameters, the arguments object was the only way to handle a variable number of arguments inside a function body. It works, but it comes with several rough edges that rest parameters were specifically designed to fix:
| Rest Parameters | arguments Object | |
|---|---|---|
| Type | Real Array | Array-like object |
| Array methods | Directly usable | Must convert first |
| Arrow functions | Works | Not available |
| Named parameters | Excluded from rest | Includes everything |
| Default values | Not on rest param | N/A |
The biggest practical advantage: rest parameters are real arrays. You can call map, filter, reduce, sort, or any array method directly, with no conversion step in between:
// With arguments (requires conversion)
function sortOld() {
const args = Array.from(arguments);
return args.sort();
}
// With rest parameters (no conversion needed)
function sortNew(...items) {
return items.sort();
}
console.log(sortNew(3, 1, 4, 1, 5)); // [1, 1, 3, 4, 5]Syntax Rules
Rest parameters have strict placement rules. Both valid forms below work because the rest parameter is always the last one in the list:
// Valid: rest parameter as the only parameter
function logAll(...items) {
console.log(items);
}
// Valid: named parameters first, then rest
function greet(greeting, ...names) {
console.log(`${greeting}, ${names.join(" and ")}!`);
}Each of the following breaks one of those rules, and each one on its own is a SyntaxError that stops the file from parsing:
// SyntaxError: rest parameter must be last
function wrong(...items, last) {}
// SyntaxError: only one rest parameter allowed
function wrong2(...a, ...b) {}
// SyntaxError: rest parameter cannot have a default
function wrong3(...items = [1, 2]) {}The rules are simple: exactly one rest parameter, always at the end, no default value.
Rest Parameters Always Produce an Array
Even when no extra arguments are passed, the rest parameter is an empty array, never undefined:
function show(a, b, ...rest) {
console.log("a:", a);
console.log("b:", b);
console.log("rest:", rest);
}
show(1, 2); // a: 1, b: 2, rest: []
show(1, 2, 3, 4); // a: 1, b: 2, rest: [3, 4]
show(1); // a: 1, b: undefined, rest: []This consistency means you can safely call array methods on the rest parameter without null checks. There is no need to write a guard clause checking whether the rest parameter exists before calling map or filter on it, since JavaScript guarantees an array every time.
Rest Parameters and function.length
Rest parameters do not contribute to the function's length property:
function f1(a, b) {} // f1.length === 2
function f2(a, b, ...rest) {} // f2.length === 2
function f3(...rest) {} // f3.length === 0The length property counts only the parameters before the first rest parameter, and before the first default parameter as well. Libraries that inspect a callback's length to decide how to call it need to be aware of this, since a rest parameter effectively hides itself from that count.
Practical Use Cases
Rest parameters show up naturally whenever a function needs to accept an open-ended list of values rather than a fixed set of named ones.
Sum or Combine Any Number of Values
function average(...numbers) {
const total = numbers.reduce((sum, n) => sum + n, 0);
return total / numbers.length;
}
console.log(average(10, 20, 30)); // 20This function accepts any number of numbers and averages them, since the reduce call and the length property both work directly on the rest array without any extra conversion step.
Collect Extra Arguments After Named Ones
Rest parameters do not have to be the only parameter. A function can take one or more named arguments first, then collect everything else into the rest parameter:
function formatList(separator, ...items) {
return items.join(separator);
}
console.log(formatList(" | ", "a", "b", "c")); // "a | b | c"The first argument is separator. Everything else goes into items, no matter how many values are passed after it.
Wrap Another Function
function logCalls(fn, ...args) {
console.log(`Calling with args:`, args);
return fn(...args);
}
function add(a, b) {
return a + b;
}
console.log(logCalls(add, 3, 4));
// Calling with args: [3, 4]
// 7Rest parameters collect the arguments. The spread operator, the same three-dot syntax used in a different position, then passes them back out into the wrapped function individually, so calling the function this way runs it exactly as if you had listed each argument by hand.
Destructuring with Rest
Rest parameters can also combine with array destructuring, which lets you skip specific positions in the collected arguments rather than keeping the whole list:
function ignoreFirstAndSecond(...[, , third, ...rest]) {
return { third, rest };
}
console.log(ignoreFirstAndSecond("a", "b", "c", "d", "e"));
// { third: "c", rest: ["d", "e"] }Rest Parameters in Arrow Functions
Since arrow functions do not have the arguments object, rest parameters are the only way to handle variable arguments:
const multiply = (multiplier, ...numbers) => {
return numbers.map(n => n * multiplier);
};
console.log(multiply(2, 1, 2, 3)); // [2, 4, 6]This is the recommended modern pattern. Even in regular functions, prefer rest parameters over arguments for cleaner, more predictable code.
For more on how parameters and arguments work, see JS Function Parameters vs Arguments Differences. For default values in parameters, see How to Use Default Parameters in JS Functions.
Rune AI
Key Insights
- Rest parameters (...args) collect extra arguments into a real JavaScript array.
- Unlike arguments, rest parameters are true arrays with map, filter, reduce, and other methods.
- Only one rest parameter is allowed per function, and it must be the last parameter.
- Rest parameters work in arrow functions, making them the modern replacement for arguments.
- If no extra arguments are passed, the rest parameter is an empty array, never undefined.
Frequently Asked Questions
What is the difference between rest parameters and the spread operator?
Can I have more than one rest parameter?
Do rest parameters work in arrow functions?
Conclusion
Rest parameters replace the arguments object with a real array, cleaner code, and predictable behavior. Use ...args to collect extra arguments in modern JavaScript. Just remember the rules: only one rest parameter, it must come last, and it always produces an array -- even when empty.
More in this topic
JavaScript While Loop Explained: A Complete Guide
A while loop repeats code as long as a condition stays true. Learn the syntax, see practical examples, and understand when a while loop is the right choice over a for loop.
JavaScript Loops Tutorial: for, while, do while
Loops let JavaScript repeat code without writing it twice. Learn the three core loop types, what each one does, and when to choose one over another.
How to Loop Through Arrays Using JS for Loops Guide
Looping through arrays is the most practical use of JavaScript for loops. Learn how to access each element by index, avoid off-by-one errors, and choose between for, for...of, and forEach.