Rest Parameters
Introduction
Rest syntax (...) collects remaining values into a single array or object. In function parameters, rest parameters replace many uses of the older arguments object with a real array.
The interview shortcut is simple: rest appears where values are being bound, while spread appears where values are being expanded.
Why This Matters
Variadic functions, wrapper utilities, reducers, event handlers, and API helpers all need a safe way to accept an unknown number of values. Rest parameters are clearer than arguments, work with arrow functions, and compose naturally with destructuring.
Theory
Rest parameters
A rest parameter gathers all remaining arguments into a real array: function log(level, ...messages). It must be the final parameter because it consumes everything left. You cannot put another parameter after it.
Rest is not arguments
arguments is array-like, not an array, and it is unavailable in arrow functions. Rest parameters are real arrays, so methods like map, filter, reduce, and slice work directly.
Destructuring rest
Rest also works in destructuring patterns. const [head, ...tail] = values collects remaining array elements. const { password, ...publicUser } = user copies remaining object properties into a new object. Like spread, object rest is shallow.
Rest vs spread in one sentence
If ... is on the left side of binding values, it collects. If it is on the right side producing values, it spreads.
Visual Diagrams
call: fn('info', 'created', 'user')
| | |
v v v
params: level ...messages collects ['created', 'user']
destructure: const [head, ...tail] = [10, 20, 30]
head = 10
tail = [20, 30]Rest syntax is a binding pattern: it creates one variable containing the remaining values.
Code Examples
Rest parameters are real arrays
A rest parameter can be filtered, mapped, reduced, or passed to another function.
Rest in destructuring
Object rest is useful for removing fields before logging or returning data.
Playground
Press Run to execute the code and see output here.
Output Prediction
Predict the output #1
1function collect(label, ...items) {2 console.log(label);3 console.log(items.length);4 console.log(Array.isArray(items));5}6 7collect('ids', 10, 20);Predict the output #2
1const [first, ...rest] = [1, 2, 3];2const copy = [...rest];3 4copy.push(4);5 6console.log(first);7console.log(rest.join('-'));8console.log(copy.join('-'));Coding Exercises
Create a flexible average function
EasyImplement average(...values) so it accepts any number of numbers and returns their average. Return 0 when no values are provided.
Interview Questions
1Why prefer rest parameters over `arguments`?
Rest parameters are explicit, named, and real arrays. They work in arrow functions and can use array methods directly. arguments is array-like, less readable, unavailable in arrows, and can have legacy aliasing behavior in non-strict functions.
2Where must a rest parameter appear in a function signature?
It must be the final parameter because it collects all remaining arguments. function f(...args, last) is a syntax error.
Follow-ups
- Can destructuring use rest?
- Is object rest a deep copy?
Quiz
1. Which declaration is valid?
2. In `const { id, ...rest } = user`, what is `rest`?
Summary
- Rest parameters collect remaining function arguments into a real array.
- A rest parameter must be the final parameter.
- Array and object destructuring can use rest to collect leftover values.
- Spread expands values; rest collects values.
Cheat Sheet
Function rest: function fn(first, ...rest) {}.
Array rest: const [head, ...tail] = items.
Object rest: const { secret, ...publicData } = user.
Rule: one rest element, and in function parameters it must be last.
Rest vs spread: rest collects; spread expands.