Advanced20 min read

Spread & Rest Operators

Master the ... syntax for spreading arrays and objects, and collecting function arguments with rest parameters.

The Spread Operator (...)

The spread operator (...) expands an iterable (like an array or object) into individual elements. It looks the same as the rest operator but works in the opposite direction.

Spread in arrays — concatenate or copy arrays:

javascript
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];

const merged = [...arr1, ...arr2];
console.log(merged); // [1, 2, 3, 4, 5, 6]

const copy = [...arr1];
console.log(copy);   // [1, 2, 3] (a new array, not a reference)

Spread in function calls — pass array elements as individual arguments:

javascript
const numbers = [5, 2, 8, 1, 9];
console.log(Math.max(...numbers)); // 9

// Without spread, you would need:
console.log(Math.max.apply(null, numbers)); // 9 (old way)

Spread in object literals — merge or copy objects:

javascript
const defaults = { theme: 'light', lang: 'en' };
const userPrefs = { theme: 'dark', fontSize: 16 };

const settings = { ...defaults, ...userPrefs };
console.log(settings);
// { theme: 'dark', lang: 'en', fontSize: 16 }

When properties overlap, later values overwrite earlier ones. This makes spread perfect for applying overrides to default settings.

The Rest Operator (...)

The rest operator also uses ... but does the opposite — it collects multiple elements into a single array.

Rest in function parameters — accept any number of arguments:

javascript
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

Unlike the old arguments object, rest parameters produce a real array with all array methods available.

Rest in array destructuring:

javascript
const [first, second, ...remaining] = [1, 2, 3, 4, 5];
console.log(first);     // 1
console.log(second);    // 2
console.log(remaining); // [3, 4, 5]

Rest in object destructuring:

javascript
const { name, ...details } = { name: 'Alice', age: 30, city: 'Paris' };
console.log(name);    // 'Alice'
console.log(details); // { age: 30, city: 'Paris' }

Important rule: The rest element must always be the last element:

javascript
const [first, ...rest, last] = [1, 2, 3]; // SyntaxError!

Common Patterns

Spread and rest enable many useful patterns in everyday JavaScript.

Cloning arrays and objects (shallow copy):

javascript
const original = [1, [2, 3], 4];
const clone = [...original];
clone[0] = 99;
console.log(original[0]); // 1 (unaffected)
// Note: nested arrays/objects are still shared (shallow copy)

Merging objects with overrides:

javascript
const config = {
  ...defaultConfig,
  ...userConfig,
  timestamp: Date.now() // always override timestamp
};

Removing properties from an object without mutation:

javascript
const user = { name: 'Alice', password: 'secret', age: 30 };
const { password, ...safeUser } = user;
console.log(safeUser); // { name: 'Alice', age: 30 }
// password is extracted but not included in safeUser

Collecting variadic arguments:

javascript
const log = (level, ...messages) => {
  console.log(`[${level}]`, ...messages);
};

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

Adding elements to an array without mutation:

javascript
const todos = ['Buy milk', 'Clean house'];
const updated = [...todos, 'Walk the dog'];
// original todos array is unchanged

Spread & Rest in Action

html
<div id="output"></div>

<script>
  // Spread: merge arrays
  const fruits = ['apple', 'banana'];
  const veggies = ['carrot', 'pea'];
  const food = [...fruits, ...veggies];

  // Spread: merge objects
  const defaults = { color: 'blue', size: 'medium' };
  const custom = { size: 'large', weight: 'bold' };
  const merged = { ...defaults, ...custom };

  // Rest: variadic function
  const sum = (...nums) => nums.reduce((a, b) => a + b, 0);

  // Rest: remove property
  const user = { name: 'Alice', password: '123', role: 'admin' };
  const { password, ...safeUser } = user;

  const output = document.getElementById('output');
  output.innerHTML = `
    <p>Food: [${food.join(', ')}]</p>
    <p>Merged: ${JSON.stringify(merged)}</p>
    <p>sum(1,2,3,4,5): ${sum(1, 2, 3, 4, 5)}</p>
    <p>Safe user: ${JSON.stringify(safeUser)}</p>
  `;
</script>

What is the difference between spread and rest?

Ready to practice?

Create your free account to access the interactive code editor, run challenges, and track your progress.