Spread & Rest Operators
Same Syntax, Opposite Directions
LinkedIn Hook
Three dots. Two completely different jobs.
...in JavaScript is a syntactic shapeshifter — sometimes it pulls an array apart into individual elements, sometimes it gathers individual elements into an array. Same three characters, opposite behavior.The position tells the whole story. On the right side of an
=or inside a function call, those dots are spread — they expand. On the left side of an=or inside a function's parameter list, those dots are rest — they collect.In this lesson you'll learn how to spread into arrays, objects, and function calls, how to collect with rest in parameters and destructuring patterns, and the one edge case most devs miss — why you can spread an array into an object, but not a plain object into an array.
Nail this lesson and half of modern JavaScript syntax suddenly reads like plain English.
Read the full lesson -> [link]
#JavaScript #Spread #Rest #ES6 #InterviewPrep #Frontend #CodingInterview
What You'll Learn
- How spread expands arrays, objects, and iterables inside array literals, object literals, and function calls
- How rest collects the remaining parameters in function signatures and destructuring patterns
- The position-based rule that lets you tell spread and rest apart at a glance
The Zipper Analogy
Same syntax (...), completely different purpose depending on context. Think of it like a zipper — pull it apart (spread) to expand, push it together (rest) to collect.
Spread — Expanding Things
Spread in arrays:
const fruits = ["apple", "banana"];
const moreFruits = ["mango", ...fruits, "grape"];
console.log(moreFruits); // ["mango", "apple", "banana", "grape"]
// Combining arrays
const arr1 = [1, 2];
const arr2 = [3, 4];
const combined = [...arr1, ...arr2]; // [1, 2, 3, 4]
Spread in objects:
const defaults = { theme: "dark", lang: "en", fontSize: 14 };
const userPrefs = { theme: "light", fontSize: 18 };
// Later properties override earlier ones
const settings = { ...defaults, ...userPrefs };
console.log(settings);
// { theme: "light", lang: "en", fontSize: 18 }
Spread in function calls:
const numbers = [5, 2, 8, 1, 9];
const max = Math.max(...numbers); // same as Math.max(5, 2, 8, 1, 9)
console.log(max); // 9
// Converting string to characters
const chars = [..."hello"]; // ["h", "e", "l", "l", "o"]
Rest — Collecting Things
Rest in function parameters:
function sum(first, second, ...remaining) {
console.log(first); // 1
console.log(second); // 2
console.log(remaining); // [3, 4, 5]
return [first, second, ...remaining].reduce((a, b) => a + b, 0);
}
sum(1, 2, 3, 4, 5); // 15
Rest in destructuring:
// Array destructuring with rest
const [head, ...tail] = [1, 2, 3, 4, 5];
console.log(head); // 1
console.log(tail); // [2, 3, 4, 5]
// Object destructuring with rest
const { name, age, ...otherInfo } = {
name: "Rakibul",
age: 25,
city: "Dhaka",
job: "Developer"
};
console.log(otherInfo); // { city: "Dhaka", job: "Developer" }
Spread vs Rest — Same Syntax, Different Context
// SPREAD — expands an array INTO individual elements
const arr = [1, 2, 3];
console.log(...arr); // 1 2 3 (expanded)
// REST — collects individual elements INTO an array
function collect(...nums) {
console.log(nums); // [1, 2, 3] (collected)
}
collect(1, 2, 3);
The rule: If ... appears on the right side of = or in a function call, it's spread. If it appears on the left side of = or in a function definition, it's rest.
Common Mistakes
- Trying to spread a plain object into an array —
[...{ a: 1 }]throws because plain objects are not iterable; only arrays, strings, Maps, and Sets are. - Placing a rest parameter before other parameters —
function fn(...args, last) {}is a SyntaxError; rest must always be last. - Assuming object spread deep-merges — it only copies top-level keys, so later spreads overwrite earlier keys wholesale instead of merging nested objects.
Interview Questions
Q: What is the difference between spread and rest operator?
They use the same
...syntax but do opposite things. Spread expands an iterable into individual elements (used in function calls, array/object literals). Rest collects multiple elements into a single array (used in function parameters, destructuring).
Q: Can you spread an object into an array or vice versa?
You can spread an array into an object:
{...[1,2,3]}gives{0:1, 1:2, 2:3}. But you cannot spread a plain object into an array:[...{a:1}]throws a TypeError because plain objects are not iterable.
Q: What does spread do in [...arr] vs fn(...arr)?
In
[...arr]it expands the iterable into a new array literal (a shallow clone). Infn(...arr)it expands the array into individual positional arguments at the call site — equivalent tofn(arr[0], arr[1], ...).
Q: What does rest do in function(...args) vs const [a, ...rest] = arr?
In the function signature, rest collects all remaining positional arguments into a real array named
args. In the destructuring pattern, rest collects all remaining elements of the array intorestafter the named bindings are taken.
Quick Reference — Cheat Sheet
SPREAD vs REST — QUICK MAP
Spread (right side / call site) -> expands:
[...arr] array-literal expansion
{ ...obj } object-literal expansion
fn(...args) function-call expansion
Math.max(...nums) pass array as positional args
[..."hi"] any iterable -> array
Rest (left side / param list) -> collects:
function fn(...args) {} gathers positional args into array
const [a, ...rest] = x gathers remaining array elements
const { a, ...rest } = x gathers remaining object keys
Rules:
- Rest parameter MUST be the last parameter
- You can only spread iterables into arrays
- Object spread is shallow (no deep merge)
Previous: Shallow Copy vs Deep Copy -> The Photocopy Trap Next: Destructuring -> Unpacking Objects & Arrays
This is Lesson 7.2 of the JavaScript Interview Prep Course — 14 chapters, 87 lessons.