Spread vs Rest Operators in JS
If you have spent any time reading modern JavaScript code, you have undoubtedly seen them: the mysterious three dots (...).
What makes these dots notoriously confusing for beginners is that they represent two completely different operators that do exactly the opposite of one another, depending entirely on where you place them.
Sometimes they unpack a neat little box into a messy pile. Other times, they scoop up a messy pile and pack it neatly into a box.
Let's break down the difference between the Spread operator (the unpacker) and the Rest operator (the scooper), and look at how to use them in the real world.
The Spread Operator: Expanding Values
Think of the Spread operator as taking items out of a container and laying them out individually. You use it when you have an array or an object, and you want to "spread" its contents out into a new array, a new object, or a function call.
1. Spreading Arrays
Before the spread operator, combining arrays or making a copy required methods like .concat() or .slice(). Now, it is incredibly visual.
const techStocks = ['AAPL', 'MSFT'];
const dividendStocks = ['KO', 'JNJ'];
// Spreading both arrays into a brand new array
const portfolio = [...techStocks, 'TSLA', ...dividendStocks];
console.log(portfolio);
// Output: ['AAPL', 'MSFT', 'TSLA', 'KO', 'JNJ']
2. Spreading Objects (Real-World Usage)
Spreading is perhaps most famous for its role in modern UI development (like React) for updating application state. Because you generally shouldn't mutate objects directly, spread allows you to copy all existing properties into a new object and just overwrite the ones you want to change.
const userState = {
username: 'Alex',
balance: 5000,
theme: 'dark'
};
// We spread the old state, and overwrite the balance
const updatedState = {
...userState,
balance: 5500
};
console.log(updatedState);
// Output: { username: 'Alex', balance: 5500, theme: 'dark' }
The Rest Operator: Collecting Values
If Spread unpacks, Rest packs. The Rest operator is used to gather up "the rest" of some scattered, individual values and bundle them tightly into a single array or object.
You will almost exclusively see the Rest operator in two places: function parameters and destructuring assignments.
1. Rest in Function Parameters
Imagine you are writing a function that calculates the total cost of a shopping cart. You don't know if the user will pass in two prices, five prices, or fifty.
Instead of forcing the user to pass an array, you can use the Rest operator to gather all the individual arguments into an array automatically.
// The ...prices gathers all arguments into an array called 'prices'
function calculateTotal(...prices) {
return prices.reduce((total, current) => total + current, 0);
}
console.log(calculateTotal(10, 20, 5)); // Output: 35
console.log(calculateTotal(99)); // Output: 99
2. Rest in Destructuring
This is a powerful pattern for extracting specific data while keeping the remaining data intact. You pull out the variables you need, and scoop "the rest" into a new variable.
const tradeDetails = {
id: 'TXN-9982',
symbol: 'GOOGL',
shares: 10,
price: 150.50
};
// We extract 'id' and 'symbol', and collect the rest into 'financials'
const { id, symbol, ...financials } = tradeDetails;
console.log(symbol); // Output: 'GOOGL'
console.log(financials); // Output: { shares: 10, price: 150.50 }
The Golden Rule: How to Tell Them Apart
If you ever get confused looking at ... in a codebase, just remember this single rule:
Is it defining a function or pulling apart variables? It is the Rest operator. It is collecting values into a variable.
Is it calling a function, or building a new array/object? It is the Spread operator. It is expanding values out of a variable.
| Operator | Action | Common Location | Example |
|---|---|---|---|
| Spread | Expands/Unpacks | Inside [], {}, or function calls |
const newArr = [...oldArr, 5]; |
| Rest | Collects/Packs | Function definitions or destructuring | const { a, ...others } = obj; |
By mastering the three dots, you eliminate clunky array methods and tedious object assignments, writing code that is much more declarative and easier to read.