Spread Operator
Three dots (...) that expand iterables into individual elements.
Array Spread
Expand an array into individual elements.
// Spread "unpacks" an array:
const nums = [1, 2, 3];
console.log(...nums); // 1 2 3 (separate arguments)
// Insert into another array:
const more = [0, ...nums, 4, 5];
// [0, 1, 2, 3, 4, 5]
// Pass array as function arguments:
function add(a, b, c) { return a + b + c; }
add(...nums); // 6 (same as add(1, 2, 3))
// Math.max with arrays:
const scores = [85, 92, 78, 95, 88];
Math.max(...scores); // 95
Math.min(...scores); // 78
// Convert iterable to array:
const chars = [..."hello"]; // ["h", "e", "l", "l", "o"]
const unique = [...new Set([1, 2, 2, 3])]; // [1, 2, 3]Object Spread
Copy and extend objects immutably.
// Spread object properties into a new object:
const defaults = { theme: "light", lang: "en", debug: false };
const userPrefs = { theme: "dark", lang: "ja" };
const config = { ...defaults, ...userPrefs };
// { theme: "dark", lang: "ja", debug: false }
// Later spreads overwrite earlier ones!
// Add/override properties:
const user = { name: "Alice", age: 25 };
const updated = { ...user, age: 26, email: "a@b.com" };
// { name: "Alice", age: 26, email: "a@b.com" }
// Remove a property (with destructuring):
const { age, ...withoutAge } = user;
// withoutAge = { name: "Alice" }
// Conditional properties:
const post = {
title: "Hello",
...( isPublished && { publishedAt: new Date() }),
...( tags.length && { tags }),
};Copying
Spread creates shallow copies — understand the limits.
// Shallow copy of arrays:
const original = [1, 2, 3];
const copy = [...original];
copy.push(4);
console.log(original); // [1, 2, 3] (unchanged)
console.log(copy); // [1, 2, 3, 4]
// Shallow copy of objects:
const obj = { a: 1, b: 2 };
const clone = { ...obj };
clone.c = 3;
console.log(obj); // { a: 1, b: 2 } (unchanged)
console.log(clone); // { a: 1, b: 2, c: 3 }Spread creates a new array/object — modifying the copy doesn't affect the original.
1 / 2
Merging
Combine arrays and objects together.
// Merge arrays:
const front = ["React", "Vue"];
const back = ["Node", "Django"];
const fullStack = [...front, ...back];
// ["React", "Vue", "Node", "Django"]
// Merge + deduplicate:
const all = [...new Set([...front, ...back, ...front])];
// Merge objects (last wins):
const base = { size: "md", color: "blue", variant: "solid" };
const override = { color: "red", size: "lg" };
const merged = { ...base, ...override };
// { size: "lg", color: "red", variant: "solid" }
// Order matters!
const a = { x: 1, y: 2 };
const b = { y: 3, z: 4 };
{ ...a, ...b } // { x: 1, y: 3, z: 4 } — b's y wins
{ ...b, ...a } // { x: 1, y: 2, z: 4 } — a's y winsPractical Patterns
Real-world uses of spread.
// 1. Immutable state updates (React):
const [todos, setTodos] = useState([]);
// Add:
setTodos([...todos, newTodo]);
// Remove:
setTodos(todos.filter(t => t.id !== id));
// Update one:
setTodos(todos.map(t => t.id === id ? { ...t, done: true } : t));
// 2. Function composition:
function withDefaults(options) {
return { method: "GET", headers: {}, ...options };
}
withDefaults({ url: "/api" }); // { method: "GET", headers: {}, url: "/api" }
// 3. Array manipulation without mutation:
const arr = [1, 2, 3, 4, 5];
// Prepend: [0, ...arr]
// Append: [...arr, 6]
// Insert: [...arr.slice(0, 2), 99, ...arr.slice(2)]
// Remove: [...arr.slice(0, 1), ...arr.slice(2)]
// 4. Convert NodeList to Array:
const divs = [...document.querySelectorAll("div")];
divs.map(d => d.textContent); // now array methods workFAQ
Common questions about the spread operator.