The same three dots as spread, the exact opposite behavior. Where spread opens a box, rest closes one: it picks up everything that was not named and files it into a single variable.
Definition
Rest, written as three dots in front of a name, gathers the remaining values into an array or an object. It shows up in two places: a function's parameter list, and a Destructuring.
// Rest parameter: a genuine array
function sum(...numbers) {
return numbers.reduce((a, b) => a + b, 0);
}
console.log(sum(1, 2, 3, 4)); // 10
// With named parameters in front
function head(first, ...tail) {
return { first, tail };
}
console.log(head("a", "b", "c")); // { first: "a", tail: ["b", "c"] }It is the direct replacement for the arguments object, with three advantages: the result is a real array, the variable carries a meaningful name, and the form works inside arrow functions.
One positioning rule
Rest must always come last, which follows from its very definition: gathering what remains only makes sense once the rest is known.
// Rejected by the engine
// function f(...values, last) {} // SyntaxError
// Accepted
function f(first, ...values) {}A rest parameter does not count toward a function's length property, which reports how many parameters are expected. A function written function sum(...n) therefore reports length as zero, which surprises anyone inspecting code.
Rest in destructuring
This is its most elegant use, and the least known among beginners. It removes a property from an object without writing a loop or modifying the original.
// On an array
const [first, ...others] = [1, 2, 3];
console.log(others); // [2, 3]
// On an object: isolate one key and keep the rest
const user = { id: 7, name: "Ada", password: "secret" };
const { password, ...safe } = user;
console.log(safe); // { id: 7, name: "Ada" }That last line is a very common server-side pattern: stripping a sensitive field before sending an object to the client. The original stays intact, and the new object never holds the discarded property.
Frequently asked questions
How do I tell rest from spread while reading?
Look at which side of the equals sign the three dots sit on, or whether they appear in a parameter list. On the left of an assignment or in a parameter list, they gather: that is rest. On the right, or inside a function call, they spread: that is Spread (...).
What does the parameter hold when no argument is passed?
An empty array, never undefined. That is a quiet but real advantage over the arguments object: you can chain an array method straight away, without first checking that there is anything to process.
Does object rest make a deep copy?
No, and it shares that limit with Spread (...): only the first level is copied. If the object holds a property that is itself an object, both versions share that nested value. For a genuinely independent copy, go through structuredClone.