🌱BeginnerModern JavaScript (ES6+)

Spread and Rest Operators

The ... syntax for expanding arrays/objects and collecting remaining values.

Overview

The three-dot syntax (...) serves two opposite but related purposes: spread expands an iterable into individual items, while rest collects multiple items into an array or object. The same punctuation, determined entirely by context. Spread is used to: copy an array (avoiding mutation), merge arrays, copy/merge objects, pass array items as function arguments, and clone objects with overrides. It is a cleaner, more expressive alternative to methods like concat() and Object.assign(). Rest is used to: collect all remaining function arguments into an array (replacing the legacy arguments object), and gather remaining properties during destructuring. Rest parameters must always be last in a parameter list.

Key Points

  • •Spread in array: [...arr] creates a shallow copy; [...a, ...b] merges arrays
  • •Spread in object: { ...obj } copies properties; { ...obj, key: val } copies and overrides
  • •Spread in function call: fn(...arr) passes array items as separate arguments
  • •Rest in function params: function f(a, b, ...rest) rest gets all remaining args as an array
  • •Rest in destructuring: const { a, ...others } = obj others has everything except a
  • •Both create shallow copies nested objects/arrays are still shared references

Examples

Spread for copying and merging arrays

const a = [1, 2, 3];
const b = [4, 5, 6];

const copy = [...a];              // shallow copy
const merged = [...a, ...b];      // merge
const withExtra = [...a, 99, ...b]; // interleave

console.log(copy);     // [1, 2, 3]
console.log(merged);   // [1, 2, 3, 4, 5, 6]
console.log(withExtra);// [1, 2, 3, 99, 4, 5, 6]

Spread for copying and overriding objects

const defaults = { theme: "light", lang: "en", font: "sans" };
const userPrefs = { lang: "fr", font: "serif" };

// Merge: later properties win
const config = { ...defaults, ...userPrefs };
console.log(config);
// { theme: "light", lang: "fr", font: "serif" }

// Add a single override
const withTitle = { ...config, title: "Dashboard" };
console.log(withTitle.title); // "Dashboard"

This pattern (spread + override) is the standard way to do immutable object updates in React.

Rest parameters collect remaining arguments

function sum(first, ...rest) {
  console.log("first:", first);
  console.log("rest:", rest);
  return first + rest.reduce((a, b) => a + b, 0);
}

console.log(sum(1, 2, 3, 4)); // first:1 rest:[2,3,4] → 10
console.log(sum(5));           // first:5 rest:[] → 5

Common Mistakes

  • Treating spread as a deep clone { ...obj } only copies one level; nested objects are still shared
  • Putting rest parameters anywhere but last: function f(...a, b) is a SyntaxError
  • Confusing Object spread with Object.assign { ...a, ...b } is equivalent to Object.assign({}, a, b)

Note

In React, you'll see the spread pattern constantly for updating state: setState({ ...currentState, updatedField: newValue }). Understanding spread makes React code much easier to read.

Exercises

Write JavaScript code to solve each exercise. Run it and check your output.

Loading editor…

Completed: 0 / 5 exercises

Knowledge Check

Question 1 of 4

What is the difference between spread and rest?