JavaScript Rest & Spread

Three Dots, Two Jobs

JavaScript Rest & Spread

The `...` operator collects values into an array (rest) or spreads them out (spread). Same syntax, opposite directions.

5 min read Level 2/5 #rest#spread#parameters
What you'll learn
  • Use `...args` to accept any number of arguments
  • Use `...arr` to spread an array into a call or literal
  • Spread objects (ES2018+)

The ... operator does two jobs — opposite directions, same syntax.

ContextWhat ... does
Function PARAMETERRest — collect remaining args into array
Function CALL siteSpread — expand an iterable into args
Array literalSpread — expand items
Object literalSpread — copy properties (ES2018)

Rest — Collect Arguments

A rest parameter gathers all remaining arguments into a real array.

Rest parameter script.js
function sum(...nums) {
  let total = 0;
  for (const n of nums) total += n;
  return total;
}

console.log(sum(1, 2, 3));        // 6
console.log(sum(10, 20, 30, 40)); // 100
console.log(sum());               // 0
▶ Preview: console

The rest parameter must be last in the parameter list.

Required params, then rest script.js
function greetAll(greeting, ...names) {
  for (const name of names) {
    console.log(`${greeting}, ${name}!`);
  }
}

greetAll("Hello", "Ada", "Lin", "Tim");
// "Hello, Ada!"
// "Hello, Lin!"
// "Hello, Tim!"
▶ Preview: console

Spread — Expand an Array

...arr in a call site expands the array’s items into separate arguments.

Spread into a call script.js
function add(a, b, c) {
  return a + b + c;
}

const nums = [1, 2, 3];
console.log(add(...nums)); // 6  ← same as add(1, 2, 3)
▶ Preview: console

A famous case: Math.max/Math.min take individual arguments, not an array. Spread bridges the gap:

Math.max with spread script.js
const scores = [88, 92, 73, 95, 81];

console.log(Math.max(...scores));  // 95
console.log(Math.min(...scores));  // 73
▶ Preview: console

Spread Into an Array Literal

Combine, copy, or insert:

Array spread script.js
const a = [1, 2];
const b = [3, 4];

const combined = [...a, ...b];           // [1, 2, 3, 4]
const withMore = [0, ...a, 5, ...b];     // [0, 1, 2, 5, 3, 4]
const copy = [...a];                      // [1, 2] — new array, same items

console.log(combined, withMore, copy);
▶ Preview: console

[...arr] is the cleanest way to copy an array.

Spread Into an Object Literal

Same idea for objects — copy and override properties.

Object spread script.js
const defaults = { theme: "light", fontSize: 14 };
const user = { fontSize: 16, language: "en" };

const settings = { ...defaults, ...user };
console.log(settings);
// { theme: 'light', fontSize: 16, language: 'en' }
▶ Preview: console

Later spreads override earlier ones, so user.fontSize wins over defaults.fontSize. This is the standard immutable-update pattern.

Rest in Destructuring (Refresher)

You’ve already seen rest in destructuring:

Rest with destructuring script.js
const [first, ...others] = [1, 2, 3, 4];
console.log(first);   // 1
console.log(others);  // [2, 3, 4]

const { a, ...rest } = { a: 1, b: 2, c: 3 };
console.log(a);    // 1
console.log(rest); // { b: 2, c: 3 }
▶ Preview: console

Try It Yourself

Exercise

Sum any number of arguments

Difficulty 2/5~3 min
Write a function `sum(...nums)` that accepts any number of numeric arguments and returns their sum. It should return `0` when called with no arguments. Test it by logging: - "`sum(1, 2, 3)` → `6`" - "`sum(10, 20, 30, 40)` → `100`" - "`sum()` → `0`"
solution.js
// declare sum here

console.log(sum(1, 2, 3));
console.log(sum(10, 20, 30, 40));
console.log(sum());
5tests will run
💡 Show hint
Use a rest parameter `...nums` to collect all arguments into an array, then `nums.reduce((a, b) => a + b, 0)`.
✅ Show solution
function sum(...nums) {
  return nums.reduce((a, b) => a + b, 0);
}

console.log(sum(1, 2, 3));
console.log(sum(10, 20, 30, 40));
console.log(sum());

Up Next

The most-used function syntax in modern JavaScript — arrow functions.

JavaScript Arrow Functions →