Skip to main content

Difference between spread and rest

The main difference in one sentence: spread unpacks elements (it expands an array or an object), while rest gathers elements (it packs the remainder into an array or an object). They are written identically, as three dots, so they are told apart by their position in the code rather than by their appearance.

Theory

TL;DR

  • Spread expands a structure: [...arr], {...obj}, fn(...args).
  • Rest packs the remainder: function fn(...args), [a, ...rest], { a, ...rest }.
  • Spread lives in a call or creation context, rest in a declaration or destructuring context.
  • The result of spread is separate elements; the result of rest is a new array or object.
  • ... is not an operator of the language on its own, it is part of the destructuring and call syntax.
  • Both perform a shallow copy.

Quick example

javascript
function logFirstAndRest(first, ...rest) { // rest gathers console.log('First:', first); console.log('Others:', rest); } const numbers = [10, 20, 30, 40]; logFirstAndRest(...numbers); // spread expands // What happens: // logFirstAndRest(10, 20, 30, 40); // first = 10 // rest = [20, 30, 40]

Spread, unpacking data

Used when a structure (an array or an object) has to be expanded into separate elements.

Array example:

javascript
const arr = [1, 2, 3]; console.log(...arr); // 1 2 3

Copying and merging:

javascript
const a = [1, 2]; const b = [3, 4]; const merged = [...a, ...b]; console.log(merged); // [1, 2, 3, 4]

Object example:

javascript
const user = { name: 'Alex', age: 25 }; const newUser = { ...user, city: 'Paris' }; console.log(newUser); // { name: 'Alex', age: 25, city: 'Paris' }

Function call example:

javascript
function sum(a, b, c) { return a + b + c; } const nums = [1, 2, 3]; console.log(sum(...nums)); // 6

One rule: spread opens a structure up.

Rest, gathering data

Used when several elements have to be collected into one structure (an array or an object).

Function example:

javascript
function sum(...numbers) { return numbers.reduce((a, b) => a + b, 0); } console.log(sum(1, 2, 3, 4)); // 10

Here ...numbers gathers every argument into the array [1, 2, 3, 4].

Array destructuring example:

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

Object destructuring example:

javascript
const user = { name: 'Alex', age: 25, city: 'Paris' }; const { name, ...info } = user; console.log(name); // Alex console.log(info); // { age: 25, city: 'Paris' }

One rule: rest collects the remainder.

Head to head comparison

CriterionSpread (...)Rest (...)
ActionUnpacks valuesGathers values
Where it is usedIn function calls, arrays, objectsIn function parameters and destructuring
ResultSeparate elementsA new array or object
Array example[...arr] gives 1, 2, 3[a, ...rest] gives rest = [2, 3]
Object example{...obj}{ a, ...rest }
Function examplesum(...nums)function sum(...nums)

When the two meet

The difference is clearest where both appear in the same piece of code.

javascript
function logFirstAndRest(first, ...rest) { console.log('First:', first); console.log('Others:', rest); } const numbers = [10, 20, 30, 40]; logFirstAndRest(...numbers); // Decoded: logFirstAndRest(10, 20, 30, 40); // first = 10 // rest = [20, 30, 40]

Spread expands numbers at the moment of the call, and rest gathers the arguments once inside the function. A simple mnemonic: spread means "expand", rest means "collect".

Common mistakes

  1. Looking for the difference in the syntax. The characters are identical; the difference is purely contextual: a call or creation context means spread, a declaration or destructuring context means rest.

  2. Calling ... a standalone operator. It is not an operator, it is part of the destructuring and call syntax, so it does not work on its own: const ...rest = arr; is a syntax error.

  3. Expecting a deep copy. Both spread and rest copy shallowly, so nested objects stay shared.

    javascript
    const state = { user: { name: 'Alex' } }; const copy = { ...state }; copy.user.name = 'Maria'; console.log(state.user.name); // Maria
  4. Putting the rest parameter anywhere but last. function fn(...args, last) {} does not parse: rest swallows everything that is left, so nothing can follow it.

  5. Confusing ...args with arguments. Rest always gives a real array and works in arrow functions, while arguments is an array-like object that arrow functions do not have.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.