Skip to main content

Command Palette

Search for a command to run...

Spread vs Rest Operators in JavaScript .

Updated
5 min read
Spread vs Rest Operators in JavaScript .
M

Hello, I’m Asim, a passionate Full Stack Developer with 1 year of hands-on experience in building scalable and user-friendly web applications. I work across both frontend and backend, enjoy solving real-world problems, and focus on writing clean, efficient, and maintainable code. I’m always eager to learn new technologies and grow as a developer.

If you've seen ... in JavaScript and wondered "wait, is this the same thing in both places?" you're not alone. The three dots look identical, but they do completely opposite things depending on where you use them.

By the end of this article, you'll never confuse them again.


The Core Idea

  • Spread ... → takes something packed, and expands it outward.

  • Rest ... → takes many loose values, and collects them inward.

Same syntax. Opposite directions. Let's visualize this.


The Spread Operator ...

Spread unpacks an iterable (array, object, string) into its individual elements. Think of it as opening a box and laying everything out on a table.

With Arrays .

const fruits = ["apple", "mango"];
const moreFruits = ["banana", ...fruits, "grape"];

console.log(moreFruits);
// ["banana", "apple", "mango", "grape"]

Without spread, you'd get a nested array not what you want:

const wrong = ["banana", fruits, "grape"];
// ["banana", ["apple", "mango"], "grape"]  

Copying an Array .

const original = [1, 2, 3];
const copy = [...original];

copy.push(4);
console.log(original); // [1, 2, 3]  
console.log(copy);     // [1, 2, 3, 4]

Merging Arrays .

const frontend = ["HTML", "CSS"];
const backend  = ["Node", "Express"];

const stack = [...frontend, ...backend];
// ["HTML", "CSS", "Node", "Express"]

Spread with Objects .

const user = { name: "Alex", age: 25 };
const updated = { ...user, city: "Karachi" };

console.log(updated);
// { name: "Alex", age: 25, city: "Karachi" }

When keys clash, the last one wins:

const defaults  = { theme: "dark", lang: "en" };
const userPrefs = { lang: "ur", fontSize: 16 };

const settings = { ...defaults, ...userPrefs };
// { theme: "dark", lang: "ur", fontSize: 16 }
//                  ^^^^ overridden by userPrefs

The Rest Operator ...

Rest does the opposite it collects multiple individual values into a single array. You'll see it in function parameters and destructuring.


Rest in Function Parameters .

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

numbers becomes a real array no matter how many arguments you pass.

First Param + Rest .

function greet(firstName, lastName, ...hobbies) {
  console.log(`\({firstName} \){lastName}`);
  console.log("Hobbies:", hobbies);
}

greet("Ahmed", "Khan", "coding", "cricket", "reading");
// Ahmed Khan
// Hobbies: ["coding", "cricket", "reading"]

Rest parameter must always come last in the parameter list.

Rest in Destructuring .

const [first, second, ...rest] = [10, 20, 30, 40, 50];
console.log(first);  // 10
console.log(rest);   // [30, 40, 50]

// Object destructuring
const { name, age, ...others } = {
  name: "Sara",
  age: 22,
  city: "Lahore",
  hobby: "painting"
};
console.log(name);   // "Sara"
console.log(others); // { city: "Lahore", hobby: "painting" }

Spread vs Rest Side by Side .

Spread ... Rest ...
What it does Expands into individual values Collects into one array
Direction One → Many Many → One
Where used Array literals, object literals, function calls Function parameters, destructuring
Position Anywhere in the expression Must be last

The easiest way to tell them apart: where is the ... in the code?

  • Inside a function call or array/object literal → Spread.

  • Inside a function definition or destructuring → Rest.


Real World Use Cases

Pass an array to a function that expects individual args .

const nums = [3, 1, 4, 1, 5];
console.log(Math.max(...nums)); // 5
// Math.max([3,1,4,1,5]) → NaN  — it needs individual values, not an array

Immutable state update in React .

const [user, setUser] = useState({ name: "Ali", age: 20 });

setUser({ ...user, age: 21 }); // only age changes, rest stays the same

Strip sensitive fields from an API response .

const apiResponse = {
  id: 101,
  token: "secret_xyz",
  name: "Fatima",
  email: "fatima@email.com"
};

const { token, ...safeData } = apiResponse;
// token is gone — safeData is safe to send to the frontend 

Build a flexible logger .

function logger(level, ...messages) { messages.forEach(msg => console.log([\({level}] \){msg})); }
logger("INFO", "Server started", "Port: 3000", "Mode: dev"); // [INFO] Server started // [INFO] Port: 3000 // [INFO] Mode: dev

One Line to Remember .

Spread = unpack and scatter → use in calls and literals .
Rest = gather and collect → use in definitions and destructuring.

Both write ... but context tells JavaScript which one you mean.


Conclusion .

The spread and rest operators are two of the most useful tools in modern JavaScript. They reduce boilerplate, make functions flexible, and help you write cleaner, more readable code.

  • Merge arrays without concat()

  • Copy objects safely without mutation

  • Accept unlimited function arguments

  • Pluck only the data you need from any structure

Open your browser console right now and try each example that's the fastest way to make it click.