Skip to main content

Command Palette

Search for a command to run...

Spread vs Rest Operators in JavaScript

Updated
3 min read

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 literalspread (expanding)
Writing ... in a function parameter or destructuringrest (collecting)