Spread vs Rest Operators in JavaScript
If you've seen ... in JavaScript code and wondered what it does — you're not alone. Those three little dots are powerful, and depending on where you use them, they behave in two completely different ways: as the spread operator or the rest operator.
Let's break each one down with simple examples.
The Spread Operator: Expanding Values
Think of the spread operator like unpacking a suitcase. It takes an array or object and spreads its contents out individually.
With arrays:
const fruits = ["apple", "banana"];
const moreFruits = [...fruits, "cherry"];
// Result: ["apple", "banana", "cherry"]
With objects:
const user = { name: "Alice", age: 25 };
const updatedUser = { ...user, city: "Paris" };
// Result: { name: "Alice", age: 25, city: "Paris" }
Here's how to picture it visually:
The Rest Operator: Collecting Values
The rest operator is the opposite — it collects multiple values and packs them into an array. You'll see it most often in function parameters.
In a function:
function addAll(...numbers) {
return numbers.reduce((sum, n) => sum + n, 0);
}
addAll(1, 2, 3, 4); // numbers = [1, 2, 3, 4] → returns 10
Collecting leftover items:
const [first, second, ...rest] = [10, 20, 30, 40, 50];
// first = 10, second = 20, rest = [30, 40, 50]
Now let's see the rest operator visually:
Spread vs Rest: Key Differences at a Glance
| Feature | Spread ... |
Rest ... |
|---|---|---|
| What it does | Expands values outward | Collects values inward |
| Used in | Arrays, objects, function calls | Function definitions, destructuring |
| Think of it as | Unpacking a box | Packing a bag |
| Result | Individual elements | A single array |
Practical Use Cases
1. Copying an array (spread)
const original = [1, 2, 3];
const copy = [...original]; // safe copy, not a reference
This is a common gotcha for beginners — without spread, const copy = original just points to the same array.
2. Merging two objects (spread)
const defaults = { theme: "light", lang: "en" };
const userSettings = { lang: "fr" };
const settings = { ...defaults, ...userSettings };
// Result: { theme: "light", lang: "fr" }
userSettings overrides defaults where keys match.
3. Flexible function arguments (rest)
function greetAll(greeting, ...names) {
names.forEach(name => console.log(`\({greeting}, \){name}!`));
}
greetAll("Hello", "Alice", "Bob", "Charlie");
// Hello, Alice!
// Hello, Bob!
// Hello, Charlie!
greeting gets the first argument, and ...names catches everything else.
4. Destructuring with rest
const scores = [98, 76, 55, 43, 30];
const [top, runner, ...others] = scores;
// top = 98, runner = 76, others = [55, 43, 30]
💡 The Golden Rule
Same syntax (...), totally different purpose depending on context.Writing
...inside a function call or array literal → spread (expanding)
Writing...in a function parameter or destructuring → rest (collecting)
