← Back to all tutorials

The Spread Operator

Master the spread operator (...) — expand arrays, clone objects, merge collections, and pass arguments.

The Spread Operator

The spread operator ... expands an iterable (array, string, object) into individual elements. It's one of the most versatile ES6 features.

Spreading Arrays

const numbers = [1, 2, 3];
console.log(...numbers);  // 1 2 3 (individual values, not an array)

// Equivalent to:
console.log(1, 2, 3);

Passing Array as Function Arguments

const scores = [85, 92, 78, 95, 88];

// Old way:
Math.max.apply(null, scores);  // 95

// ES6 way:
Math.max(...scores);  // 95 ✅ much cleaner!

Copying Arrays

const original = [1, 2, 3];

// Shallow copy:
const copy = [...original];

copy.push(4);
console.log(original);  // [1, 2, 3] — unchanged!
console.log(copy);      // [1, 2, 3, 4]

This creates a shallow copy — nested objects/arrays are still shared references.

Merging Arrays

const fruits = ["apple", "banana"];
const veggies = ["carrot", "spinach"];

// Old way:
const food = fruits.concat(veggies);

// ES6 way:
const food = [...fruits, ...veggies];
// ["apple", "banana", "carrot", "spinach"]

// Insert items in between:
const all = ["start", ...fruits, "middle", ...veggies, "end"];
// ["start", "apple", "banana", "middle", "carrot", "spinach", "end"]

Spreading Objects

const defaults = { theme: "dark", fontSize: 14, lang: "en" };
const userPrefs = { fontSize: 18, lang: "fr" };

// Merge objects (later properties win):
const settings = { ...defaults, ...userPrefs };
// { theme: "dark", fontSize: 18, lang: "fr" }

// Clone an object:
const clone = { ...defaults };

// Add/override properties:
const updated = { ...defaults, fontSize: 20, newProp: true };
// { theme: "dark", fontSize: 20, lang: "en", newProp: true }

Spreading Strings

const word = "Hello";
const letters = [...word];
// ["H", "e", "l", "l", "o"]

Rest Parameters (The Opposite)

The same ... syntax is used for rest parameters — collecting multiple arguments into an array:

function sum(...numbers) {
    return numbers.reduce((total, n) => total + n, 0);
}

sum(1, 2, 3);        // 6
sum(10, 20, 30, 40); // 100

// Rest must be the LAST parameter:
function log(level, ...messages) {
    messages.forEach(msg => console.log(`[${level}] ${msg}`));
}

log("INFO", "Server started", "Listening on port 3000");
// [INFO] Server started
// [INFO] Listening on port 3000

Spread vs Rest

ContextNameBehavior
Function call / array literalSpreadExpands an array/object into elements
Function parameterRestCollects elements into an array

Practical Patterns

// Remove first element (immutably)
const [first, ...rest] = [1, 2, 3, 4];
// first = 1, rest = [2, 3, 4]

// Add item to array (immutably)
const newArr = [...oldArr, newItem];

// Remove item from array (immutably)
const without = arr.filter(item => item.id !== removeId);

// Update object property (immutably)
const updated = { ...user, name: "New Name" };

Key Takeaways

  • ... (spread) expands arrays and objects into individual elements
  • ... (rest) collects multiple arguments into an array
  • Use spread to copy, merge, and combine arrays and objects
  • Spread creates shallow copies — nested references are shared
  • Later properties win when merging objects
  • Essential for immutable data patterns in React and Redux