JavaScript Spread and Rest
The three dots ... have two jobs. Spread expands an iterable into separate positions. Rest collects items or properties that remain. The dots look identical; their position tells you which job they perform.
Spread expands values
const extras = ["mint", "lemon"];
const menu = ["tea", ...extras];
console.log(menu.join(" / "));
The printed line is exactly tea / mint / lemon. Spread is useful when constructing an array or passing separate arguments to a function.
Copying with array spread
const extras = ["mint", "lemon"];
const copy = [...extras];
copy[0] = "ginger";
console.log(extras[0]);
console.log(copy[0]);
This is a shallow copy, not a deep copy. If an array item is an object or another array, both outer arrays still refer to that nested value.
Spread an object
const order = { guest: "lida", drink: "tea" };
const withSize = { ...order, size: "regular" };
console.log(order.size);
console.log(withSize.size);
order.size is undefined, while withSize.size is regular. Object spread is shallow too: a nested object would still be shared.
Rest gathers what remains
const menu = ["tea", "mint", "lemon"];
const [first, ...remaining] = menu;
const order = { guest: "lida", drink: "tea" };
const { guest, ...details } = order;
console.log(first, remaining, details);
Here first is tea, remaining is ["mint", "lemon"], and details contains drink but not guest.
Rest parameters
<!doctype html>
<html lang="en">
<head><meta charset="utf-8"><title>Spread and Rest</title></head>
<body>
<p id="result"></p>
<script>
const extras = ["mint", "lemon"];
const menu = ["tea", ...extras];
function list(first, ...others) {
return [first, ...others].join(" / ");
}
document.getElementById("result").textContent = list(...menu);
</script>
</body>
</html>
The page calls list(...menu): spread expands menu at the call site, then rest gathers the received values inside list. The visible result is tea / mint / lemon.
The table makes the contrast explicit: the dots stay the same, but their position decides whether JavaScript expands values or gathers what remains.
📊 Same dots, different direction
| Position | Meaning | Example |
|---|---|---|
| Array, object, or function call | Spread expands | [..., extras], { ...order }, list(...menu) |
| Binding or parameter | Rest gathers | const [first, ...remaining] = menu, function list(first, ...others) |
Practice
Change copy[0], then compare it with extras[0]. Add a nested object to an array and observe why spread is only shallow.
mistakes
Do not write rest in the middle of a parameter list, expect it to deep-copy nested data, or confuse [...items] with const [...items]. Spread expands; rest gathers.
Key point
Use the same ... carefully: spread appears where JavaScript needs separate values, while rest appears where a binding or parameter needs the remaining values.
🧠 Test Your Knowledge
Test Your Knowledge
Challenge yourself with this interactive quiz and see how well you understand the topic
📝 Instructions
- Read each question carefully
- Select the best answer for each question
- You can retake the quiz as many times as you want
- Your progress will be shown at the top