Spread/Rest β What the Three Dots Do
After completing this topic, you will:
Understand that ... has two roles: "Spread" and "Rest."
The Same Symbol, Different Roles
In JavaScript, ... has different roles depending on its location:
- Spread: "Expands" an array or object.
- Rest: "Collects" the remaining values.
It's the same ..., but it performs opposite operations depending on where it's used.
Spread: Expanding
Expanding an array:
const a = [1, 2, 3];
const b = [0, ...a, 4];
// [0, 1, 2, 3, 4]...a unpacks each element of the array a and lists them out. It's also used when copying an array:
const original = [1, 2, 3];
const copy = [...original];Expanding an object:
const defaults = { theme: "light", lang: "ko" };
const userSettings = { lang: "en", fontSize: 14 };
const config = { ...defaults, ...userSettings };
// { theme: "light", lang: "en", fontSize: 14 }The object that comes later overwrites the same keys. This is a pattern for merging default settings with user settings.
It's also used when passing an array as a function argument:
const nums = [3, 1, 4, 1, 5];
Math.max(...nums); // 5Rest: Collecting
In a function parameter, it receives "all the rest" as an array:
function sum(first, ...rest) {
console.log(first); // 1
console.log(rest); // [2, 3, 4, 5]
return rest.reduce((a, b) => a + b, first);
}
sum(1, 2, 3, 4, 5); // 15...rest collects all the elements after the first argument into an array.
It's also used in destructuring:
const [head, ...tail] = [1, 2, 3, 4];
// head: 1, tail: [2, 3, 4]
const { name, ...others } = { name: "Alice", age: 25, city: "Seoul" };
// name: "Alice", others: { age: 25, city: "Seoul" }It's useful when you want to extract specific properties and collect the rest separately.
How to Distinguish Between Spread and Rest
// Spread β "Expands" on the "giving" side
const arr = [...other];
func(...args);
// Rest β "Collects" on the "receiving" side
function func(...params) {}
const [a, ...rest] = arr;On the "sending" side (right side of assignment, function call), it's Spread. On the "receiving" side (left side of assignment, function declaration), it's Rest.
Practical Pattern: Immutable Updates
In React, you should not directly modify the original state when updating state. Use Spread to create a new object:
const [user, setUser] = useState({ name: "Alice", age: 25 });
setUser({ ...user, age: 26 });When adding an element to an array:
const [items, setItems] = useState(["a", "b"]);
setItems([...items, "c"]); // Add to the end
setItems(["z", ...items]); // Add to the beginningIt creates a new array/object without touching the original.
Key Takeaway
...is Spread (expanding) on the "sending" side and Rest (collecting) on the "receiving" side. You can use Spread to copy and merge arrays/objects, and Rest to collect the remaining values. It's a pattern that is frequently used in React for immutable state updates.