Loading...
Loading...
Three dots (...) that expand or collect values.
The spread operator (...) expands an array, object, or string into individual values, as in [...a, ...b] or { ...obj }. The rest operator uses the same three dots to collect values into an array, as in function f(...args). Spread unpacks; rest gathers. Both copy only one level deep, so nested objects stay shared.
Step through this example in the visualizer
JavaScript's core data structures are arrays (ordered lists accessed by index) and objects (key-value records accessed by name). Almost all real-world data, such as a list of products, a user profile, or an API response, is some combination of the two, so creating, reading, updating, and looping over them is essential for any project.
This module covers array methods like map and filter, object property access, destructuring assignment, the spread operator, and JSON: the format every REST API speaks. Visual memory diagrams show how references and copies behave so you avoid common mutation bugs.
Spread and rest appear in almost every modern codebase: copying React state, merging config objects, forwarding function arguments, and separating a few fields from the rest of an object. Mixing the two up, or assuming spread makes a deep copy, causes mutation bugs that are hard to trace.
Expand an array into individual elements.
const nums = [1, 2, 3]; // Spread into a new array: const copy = [...nums]; // [1, 2, 3] // Combine arrays: const a = [1, 2]; const b = [3, 4]; const merged = [...a, ...b]; // [1, 2, 3, 4] // Add elements: const withExtra = [0, ...nums, 4]; // [0, 1, 2, 3, 4] // Spread into function arguments: Math.max(...nums); // 3 console.log(...nums); // 1 2 3
const merged = [...a, ...b]
Copy and merge object properties.
const defaults = { theme: "light", lang: "en", fontSize: 14 }; const userPrefs = { theme: "dark", fontSize: 16 }; // Merge (later values win): const config = { ...defaults, ...userPrefs }; // { theme: "dark", lang: "en", fontSize: 16 } // Clone an object: const clone = { ...original }; // Add/override properties: const updated = { ...user, lastLogin: new Date() };
⚠️ Object spread creates a shallow copy. Nested objects are still shared references. Use structuredClone() for deep copies.
Collect remaining arguments into an array.
// Collect all arguments: function sum(...numbers) { return numbers.reduce((total, n) => total + n, 0); } sum(1, 2, 3); // 6 sum(1, 2, 3, 4, 5); // 15 // Mix named + rest: function log(level, ...messages) { console.log(`[${level}]`, ...messages); } log("ERROR", "Failed to", "connect"); // [ERROR] Failed to connect // Rest must be last: function bad(a, ...rest, b) {} // ✗ SyntaxError!
...spread (expand)
[...arr] or fn(...arr)
Unpacks into individual values
...rest (collect)
fn(...args) or {...rest}
Packs individual values into one
Collect remaining properties/elements.
// Object rest: const { id, ...rest } = { id: 1, name: "Alice", age: 28 }; // id = 1 // rest = { name: "Alice", age: 28 } // Array rest: const [first, ...others] = [10, 20, 30, 40]; // first = 10 // others = [20, 30, 40] // Useful for removing properties: const { password, ...safeUser } = userWithPassword; // safeUser has everything except password
Real-world spread/rest usage.
Immutable array operations
const arr = [1, 2, 3]; // Add to end (instead of push): const added = [...arr, 4]; // Remove by index: const removed = [...arr.slice(0, 1), ...arr.slice(2)]; // Replace at index: const replaced = [...arr.slice(0, 1), 99, ...arr.slice(2)];
React state patterns
// Update object state: setUser({ ...user, name: "New Name" }); // Add to array state: setItems([...items, newItem]); // Remove from array state: setItems(items.filter(i => i.id !== targetId));
Function composition
// Forward all arguments: function wrapper(...args) { console.log("Calling with:", args); return originalFn(...args); }
Common questions about spread & rest.