Technology · JavaScript
JavaScript Spread and Rest
Use spread operator for arrays and objects, rest parameters for flexible function arguments.
TL;DR
- 01Use ... to spread array or object elements into new contexts.
- 02Use rest parameters to collect arguments into an array.
- 03Spread and rest look the same but work in opposite directions.
Spread with Arrays
- Use spread to expand array elements into a new array.
const arr1 = [1, 2, 3]; const arr2 = [4, 5, 6]; const combined = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6] - Insert elements at specific positions using spread.
const arr = [1, 2, 5]; const updated = [1, 2, 3, 4, ...arr.slice(2)]; // [1, 2, 3, 4, 5] - Copy an array without reference using spread.
const original = [1, 2, 3]; const copy = [...original]; // Modifying copy doesn't affect original - Pass array elements as individual arguments to functions.
const numbers = [1, 2, 3]; Math.max(...numbers); // 3 - Spread works with any iterable, including strings and Sets.
const unique = [...new Set([1, 1, 2, 2, 3])]; // [1, 2, 3]
Spread with Objects
- Use spread to copy and merge object properties.
const user = { name: "Alice", age: 30 }; const updated = { ...user, age: 31 }; // { name: "Alice", age: 31 } - Later properties override earlier ones when spreading.
const base = { a: 1, b: 2 }; const override = { ...base, b: 3 }; // { a: 1, b: 3 } - Merge multiple objects using multiple spreads.
const obj1 = { a: 1 }; const obj2 = { b: 2 }; const obj3 = { c: 3 }; const merged = { ...obj1, ...obj2, ...obj3 }; - Spread only copies top-level properties, not nested values.
const original = { user: { name: "Alice" } }; const copy = { ...original }; // copy.user and original.user reference the same object - Add or remove properties using spread with destructuring.
const { password, ...safeUser } = user; // password is removed, rest copied to safeUser
Rest Parameters
- Use rest syntax to collect remaining function arguments into an array.
function sum(...numbers) { return numbers.reduce((a, b) => a + b, 0); } sum(1, 2, 3, 4); // 10 - Rest parameter must be the last parameter in the function.
function greet(greeting, ...names) { console.log(`${greeting} ${names.join(", ")}`); } greet("Hello", "Alice", "Bob", "Charlie"); - Use rest with destructuring to separate specific values.
const [first, ...rest] = [1, 2, 3, 4]; // first = 1, rest = [2, 3, 4] - Combine named parameters with rest for flexible APIs.
function config(name, version, ...options) { // name and version are required, options are optional } - Rest gives you a real array so array methods work directly on it.
function logAll(...messages) { messages.forEach(msg => console.log(msg)); console.log('Total:', messages.length); } logAll('a', 'b', 'c');
Spread vs Rest
- Spread expands elements, rest collects them.
// Spread: expanding an array const arr = [1, 2, 3]; const expanded = [...arr]; // Expands into individual elements // Rest: collecting arguments function collect(...args) { // Collects arguments into an array } - Spread is used in function calls and literals.
Math.max(...[1, 2, 3]); // Spread in call const arr = [1, ...rest]; // Spread in literal const obj = { ...user }; // Spread in literal - Rest is used in function parameters and destructuring.
function fn(...args) { } // Rest in parameters const [a, ...rest] = arr; // Rest in destructuring const { x, ...rest } = obj; // Rest in destructuring - Spread creates a shallow copy; rest collects into a new array or object.
const original = [1, 2, 3]; const copy = [...original]; // spread: new array, same values const [first, ...remaining] = original; // rest: collects into array - Use spread to pass variable-length data into fixed-arity functions.
const args = [1, 5, 3, 9, 2]; Math.min(...args); // 1 — spread turns array into individual args Math.max(...args); // 9
Common Patterns
- Clone and update arrays without mutation.
const items = [1, 2, 3]; const updated = [...items, 4]; const removed = items.filter(i => i !== 2); - Combine shallow cloning with merging.
const defaults = { timeout: 5000, retries: 3 }; const custom = { timeout: 10000 }; const config = { ...defaults, ...custom }; - Use rest in destructuring to handle extra values.
const [head, ...tail] = [1, 2, 3, 4]; // head = 1, tail = [2, 3, 4] - Spread into template literals with objects.
const defaults = { a: 1, b: 2 }; const custom = { b: 3, c: 4 }; const final = { ...defaults, ...custom };
Tip: Use spread for shallow cloning and merging, but remember it only copies top-level properties — use structuredClone for deep clones.
Warning: Spread on objects only copies own properties, not inherited ones or non-enumerable properties from the prototype chain.