Destructuring, spread, and rest all use similar-looking syntax (... and bracket patterns) but do genuinely different things — worth being precise about which is which.
// Destructuring: extract values into named variables
const { name, age = 18 } = { name: 'Alice' }; // age defaults to 18
const [first, second, ...remaining] = [1, 2, 3, 4, 5];
// Spread: expand an iterable into individual elements
const combined = [...[1, 2], ...[3, 4]]; // [1, 2, 3, 4]
const merged = { ...{a: 1}, ...{b: 2} }; // {a: 1, b: 2}
console.log(Math.max(...[3, 1, 4, 1, 5])); // spread into function arguments
// Rest: collect remaining items into an array/object (opposite of spread)
function sum(...numbers) { // rest parameter
return numbers.reduce((a, b) => a + b, 0);
}
const { id, ...otherProps } = { id: 1, name: 'x', active: true };
The way to tell spread and rest apart despite identical ... syntax: spread expands a collection (used where a value is expected), rest collects values (used in a destructuring pattern or function parameters) — context determines which one you’re looking at.