... shows up in two completely different roles in JavaScript, and confusing them is one of the most common early mixups. Both look identical on the page — three dots — but one expands a collection into individual pieces, and the other collects individual pieces back into a single array. This guide draws a clear, lasting line between the two.
What the Spread Operator Does
Spread syntax expands an iterable into individual values in array literals, function calls, and other supported contexts.
const numbers = [1, 2, 3];
console.log(...numbers); // 1 2 3 — not "[1, 2, 3]"
Notice console.log(...numbers) doesn't print the array itself — it prints each individual number, spread out as separate arguments. That's the core idea: In iterable contexts, spread takes one collection and expands it into individual values. Object spread is different: it copies an object's enumerable own properties into a new object.
What the Rest Operator Does
Rest does the exact opposite — it takes multiple individual values and collects them into a single array.
functionsum(...numbers) { console.log(numbers); // [1, 2, 3] — collected into one array }
sum(1, 2, 3);
Here, ...numbers in the function's parameter list gathers however many arguments were actually passed into one real array, called numbers, inside the function.
Differences Between Spread and Rest
A genuinely reliable way to tell them apart at a glance: if ... appears on the value being provided (an existing array, an existing object), it's spread. If it appears on the parameter or variable receiving values, it's rest.
Spreading into a new array creates a genuinely separate copy — modifying copy doesn't affect original, unlike simply writing const copy = original, which would just point both variables at the exact same array.
This pattern — spread the original, then override specific properties — is extremely common for updating an object without mutating the original, which matters a lot in frameworks like React, where state is expected to be replaced, not directly modified.
Practical Use Cases
Passing an array’s values as individual function arguments
functionadd(a, b, c) { return a + b + c; }
const nums = [1, 2, 3]; console.log(add(...nums)); // 6 — spreads the array into three separate arguments
first captures just the first argument; ...others (rest) gathers everything remaining into an array — a common pattern when a function needs to handle a fixed first argument plus a flexible, variable number of additional ones.
rest here collects every property exceptname into a new object — useful for pulling out one specific value while keeping "everything else" grouped together.
Spread makes it easy to layer custom overrides on top of sane defaults — later spread values override earlier ones for any matching key, which is exactly why userSettings comes second here.
Final Takeaway
Spread and rest share the exact same syntax because they’re really two faces of the same idea, pointed in opposite directions. Spread takes something already grouped together and pulls it apart into individual pieces — copying arrays, merging objects, or passing an array’s values as separate function arguments. Rest takes individual, separate values and gathers them back into one array — handling a flexible number of function arguments, or splitting “this one property” from “everything else” during destructuring. Once you’re reliably asking “is this expanding a collection, or gathering loose values into one?”, telling them apart stops being a guessing game.
Frequently Asked Questions
Can spread and rest be used in the same line of code?
> Yes — for example, const [first, ...rest] = [...combinedArray] uses spread to build combinedArray into a new array, and rest to then destructure it into first and the remaining rest. They're commonly combined once each is individually understood.
Does spreading an array or object create a deep copy?
> No — spread creates a shallow copy. Top-level properties are copied independently, but if a property’s value is itself an object or array, both the original and the copy still reference that same nested object underneath.
Can rest parameters be used anywhere in a function’s parameter list?
> No — a rest parameter must be the last parameter in the list, since it collects “everything remaining.” Placing anything after it would be ambiguous and is not allowed by JavaScript’s syntax rules.
Is the spread operator only for arrays?
> No — while spread originated with arrays, it also works with objects (since ES2018) and with any iterable value, like strings ([...\"abc\"] produces [\"a\", \"b\", \"c\"]).
Originally published by Mr Madhukar
Read the complete article on Medium with full formatting & reader responses.