Spread and Rest
Learn how the spread and rest operators work with arrays in JavaScript.
Spread and Rest
Both spread and rest use the same three dots ... syntax — but they do opposite things depending on where you use them.
- Spread — takes an array and expands it into individual items
- Rest — takes individual items and collects them into an array
// Spread — array → individual items
const numbers = [1, 2, 3];
console.log(...numbers); // 1 2 3
// Rest — individual items → array
function sum(...numbers) {
return numbers.reduce((total, n) => total + n, 0);
}
console.log(sum(1, 2, 3)); // 6Same syntax, opposite direction. Context decides which one it is.
Spread Operator
The spread operator expands an array into its individual items wherever a list of values is expected.
Copying an Array
The most common use — making a real independent copy of an array.
const original = [1, 2, 3];
const copy = [...original];
copy.push(4);
console.log(original); // [1, 2, 3] — unchanged
console.log(copy); // [1, 2, 3, 4]Without spread, copy = original would make both variables point to the same array. Spread creates a fresh independent copy.
Merging Arrays
Combine two or more arrays into one new array.
const first = [1, 2, 3];
const second = [4, 5, 6];
const merged = [...first, ...second];
console.log(merged); // [1, 2, 3, 4, 5, 6]You can add extra items while merging:
const merged = [0, ...first, ...second, 7];
console.log(merged); // [0, 1, 2, 3, 4, 5, 6, 7]Passing Array Items as Function Arguments
Spread lets you pass array items as separate arguments to a function.
function add(a, b, c) {
return a + b + c;
}
const numbers = [1, 2, 3];
console.log(add(...numbers)); // 6Without spread you would have to write add(numbers[0], numbers[1], numbers[2]).
A real use with built-in functions:
const scores = [88, 72, 95, 61, 99];
console.log(Math.max(...scores)); // 99
console.log(Math.min(...scores)); // 61Math.max() and Math.min() expect individual arguments — not an array. Spread converts the array into the separate values they expect.
Adding Items to an Array Without Mutating
Instead of push() which modifies the original, spread lets you create a new array with the added item.
const tasks = ["Write docs", "Review PR"];
// Adding without mutating — returns new array
const updatedTasks = [...tasks, "Fix bug"];
console.log(tasks); // ["Write docs", "Review PR"] — unchanged
console.log(updatedTasks); // ["Write docs", "Review PR", "Fix bug"]// Add to the beginning
const withUrgent = ["Deploy hotfix", ...tasks];
console.log(withUrgent); // ["Deploy hotfix", "Write docs", "Review PR"]This pattern is important in React and other frameworks where you should never mutate state directly.
Spreading a String
Strings are iterable — spread works on them too, splitting into individual characters.
const word = "hello";
const chars = [...word];
console.log(chars); // ["h", "e", "l", "l", "o"]Rest Operator
We covered rest parameters in the Functions section. Here is a quick recap of how it works with arrays specifically.
The rest operator collects multiple individual values into a single array. It is used in two places — function parameters and destructuring.
Rest in Function Parameters
function sum(...numbers) {
return numbers.reduce((total, n) => total + n, 0);
}
console.log(sum(1, 2, 3)); // 6
console.log(sum(10, 20, 30, 40)); // 100No matter how many arguments you pass, they all land in the numbers array.
Combine with regular parameters — rest must be last:
function announce(title, ...names) {
console.log(`${title}:`);
names.forEach(name => console.log(` - ${name}`));
}
announce("Winners", "Ali", "Sara", "Zara");
// Winners:
// - Ali
// - Sara
// - ZaraRest in Array Destructuring
const [first, second, ...remaining] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(second); // 2
console.log(remaining); // [3, 4, 5]Real use — separating the first item from the rest:
const [topStudent, ...otherStudents] = ["Ali", "Sara", "Zara", "Omar"];
console.log(`Top student: ${topStudent}`);
// Top student: Ali
console.log(`Others: ${otherStudents.join(", ")}`);
// Others: Sara, Zara, OmarSpread vs Rest — Side by Side
const numbers = [1, 2, 3, 4, 5];
// SPREAD — expands array into individual values
console.log(Math.max(...numbers)); // 5
// REST — collects individual values into array
function total(...numbers) {
return numbers.reduce((sum, n) => sum + n, 0);
}
console.log(total(1, 2, 3, 4, 5)); // 15Spread ... | Rest ... | |
|---|---|---|
| Direction | Array → individual items | Individual items → array |
| Used in | Function calls, array literals | Function parameters, destructuring |
| Purpose | Expand and copy | Collect and gather |
A Real Example — Shopping Cart
const cart = ["Laptop", "Mouse"];
const newItems = ["Keyboard", "Monitor"];
// Merge carts without mutating either
const fullCart = [...cart, ...newItems];
console.log(fullCart);
// ["Laptop", "Mouse", "Keyboard", "Monitor"]
// Remove first item (Laptop) and keep the rest
const [removed, ...remainingCart] = fullCart;
console.log(`Removed: ${removed}`);
// Removed: Laptop
console.log(`Remaining: ${remainingCart.join(", ")}`);
// Remaining: Mouse, Keyboard, Monitor
// Calculate total (pretend each item has a price)
const prices = [120000, 1500, 4500, 45000];
const total = prices.reduce((sum, price) => sum + price, 0);
console.log(`Total: Rs. ${total}`);
// Total: Rs. 171000A Real Example — Combining and Deduplicating
const team1 = ["Ali", "Sara", "Zara"];
const team2 = ["Omar", "Sara", "Hassan"];
// Merge both teams — Sara appears twice
const combined = [...team1, ...team2];
console.log(combined);
// ["Ali", "Sara", "Zara", "Omar", "Sara", "Hassan"]
// Remove duplicates using a Set
const unique = [...new Set(combined)];
console.log(unique);
// ["Ali", "Sara", "Zara", "Omar", "Hassan"]new Set() only keeps unique values. Spreading it back into an array converts the Set into a regular array. This two-liner is the cleanest way to deduplicate an array in JavaScript.
We cover Set in full detail in the ES6+ section. For now just know that spreading into a Set and back is the standard way to remove duplicates from an array.
Summary
- Both spread and rest use
...— context determines which one - Spread expands an array into individual items — used in function calls and array literals
- Rest collects individual items into an array — used in function parameters and destructuring
- Use spread to copy arrays without mutation —
[...original] - Use spread to merge arrays —
[...a, ...b] - Use spread to pass array items as function arguments —
fn(...array) - Use rest to accept any number of arguments in a function —
function fn(...args) - Use rest in destructuring to collect remaining items —
const [first, ...rest] = array - Spread into a
Setand back is the cleanest way to remove duplicates