Rest and spread both use the same ... syntax, which confuses a lot of people learning JavaScript — but they do opposite things. Rest collects multiple values into a single array. Spread expands a single array (or object) out into individual values. Which one you're looking at depends entirely on where the ... appears.
Rest: Collecting Arguments into an Array
In a function parameter list, ... gathers any remaining arguments into a real array. This is useful when a function needs to accept an unknown number of arguments.
function sum(...numbers) {
// 'numbers' is a real array, so array methods work directly on it
return numbers.reduce((total, n) => total + n, 0);
}
console.log(sum(1, 2, 3));
console.log(sum(10, 20, 30, 40));
Output:
6
100
Rest can also come after named parameters, as long as it's the last one in the list:
function introduce(firstName, ...otherDetails) {
console.log(firstName, "-", otherDetails.join(", "));
}
introduce("Sam", "25 years old", "Developer", "Seattle");
Output:
Sam - 25 years old, Developer, Seattle
Spread: Expanding an Array or Object
Spread does the reverse — it takes an existing array or object and expands its contents. A very common use is copying or merging arrays without mutating the original:
const nums1 = [1, 2, 3];
const nums2 = [4, 5, 6];
const combined = [...nums1, ...nums2];
const copy = [...nums1]; // a shallow copy, not a reference to the original
console.log(combined);
console.log(copy);
Output:
[ 1, 2, 3, 4, 5, 6 ]
[ 1, 2, 3 ]
Spread works on objects too, which makes it the standard way to merge objects or create an updated copy of one:
const user = { name: "Lee", role: "member" };
const updatedUser = { ...user, role: "admin" };
console.log(updatedUser);
Output:
{ name: 'Lee', role: 'admin' }
Spread can also expand an array directly into individual function arguments — for example, Math.max(...nums1) passes each element of nums1 as a separate argument, instead of passing the whole array as one.
Telling Them Apart
The simplest rule: if ... appears where values are being received (a function's parameter list, or the left side of a destructuring assignment), it's rest. If it appears where values are being supplied (inside an array literal, object literal, or function call), it's spread. Both are essential once you start working heavily with arrays and objects, especially when you want to update data immutably.
