RiaChoi Text Logo.
Spread vs Rest

JavaScript

Spread vs Rest

The same Three Dots, Two Opposite Jobs

Ria ChoiAugust 29th, 2026

JavaScript uses the same three dots, , for two different features: the spread operator and the rest parameter. They look identical, but they do opposite jobs. The trick to telling them apart is simple: it depends on where the dots show up.

 

🍞🥄 Spread Operator: Unpacking Things

Spread takes a collection and unpacks it into individual pieces.

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

const obj = { a: 1, b: 2 };
const copy = { ...obj, c: 3 };
// { a: 1, b: 2, c: 3 }

You use spread inside a function call, an array literal, or an object literal. It expands a single value into many.

🧺 Rest Parameter: Gathering Things

Rest does the opposite. It takes many separate values and gathers them into a single array.

function sum(...nums) {
  return nums.reduce((a, b) => a + b, 0);
}

sum(1, 2, 3, 4); 
// nums becomes [1, 2, 3, 4]

You use rest only in a function’s parameter list. It collapses many arguments into one array.

The Rule of Thumb

Same symbol, opposite direction, and the position tells you which one you are looking at.

rule_of_thumbs
Rule of Thumbs

Debounce and Throttle

This pattern is easiest to see in a higher-order function, meaning a function that takes another function as an argument and returns a new function.

For example, I was looking back at some of the code examples I wrote, and I found the pattern when implementing throttle.

function throttle(fn, limit) {
  let inThrottle;
  return (...args) => {   // rest: gather the incoming arguments into an array
    if (!inThrottle) {
      fn(...args);         // spread: unpack that array back into arguments
      inThrottle = true;
      setTimeout(() => inThrottle = false, limit);
    }
  };
}

Let’s break down the two roles in this code.

  • fn is the function you actually want to run. It is passed in as a parameter to the higher-order function throttle.
  • args represents whatever arguments the caller wants to pass into fn later, whether that is zero arguments, one, or ten.
  1. The returned function uses rest to gather them all into args.
  2. When it is time to actually call fn, it uses spread to unpack args back into individual arguments, so fn receives them exactly as if it had been called directly.
Rest collects, Spread releases, and the values pass through unchanged.

Share

Related contents