DocsHub
Arrays

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)); // 6

Same 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)); // 6

Without 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)); // 61

Math.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)); // 100

No 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
//   - Zara

Rest 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, Omar

Spread 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)); // 15
Spread ...Rest ...
DirectionArray → individual itemsIndividual items → array
Used inFunction calls, array literalsFunction parameters, destructuring
PurposeExpand and copyCollect 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. 171000

A 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 argumentsfn(...array)
  • Use rest to accept any number of arguments in a function — function fn(...args)
  • Use rest in destructuring to collect remaining itemsconst [first, ...rest] = array
  • Spread into a Set and back is the cleanest way to remove duplicates

On this page