JavaScript Spread and Rest
Use spread syntax to expand arrays and objects, and rest parameters to handle variable function arguments.
TL;DR
- 01Use
...to expand array elements or object properties into context. - 02Gather remaining variables or function arguments using the rest syntax.
- 03Ensure rest parameters reside at the end of argument signatures.
Tips
- 01Leverage object spread syntax to create shallow copies and merge multiple objects without mutating originals.
- 02Combine rest parameters and array destructuring to extract specific list elements and collect the rest.
Warnings
- 01Remember that object spread performs a shallow copy, leaving nested object references shared between copies.
- 02Placing a rest parameter before other parameters in a function signature throws a
SyntaxError.
Spread with Arrays
Array mergingCombines elements of multiple arrays into a new array literal context.
const arr1 = [1, 2];
const arr2 = [3, 4];
const merged = [...arr1, ...arr2]; // [1, 2, 3, 4]Array copyCreates a shallow copy of an array, breaking the original reference link.
const original = [1, 2, 3];
const copy = [...original];Function argumentsExpands array items into individual parameters for function execution calls.
const numbers = [5, 10, 3];
Math.max(...numbers); // 10Iterable spreadConverts strings or Sets into arrays using the spread operator.
const chars = [..."hi"]; // ["h", "i"]Spread with Objects
Object mergingMerges property fields of multiple objects into a new object container.
const user = { name: "Alice", age: 30 };
const updated = { ...user, active: true };Property overrideApplies new values to keys by placing overrides after the spread target.
const base = { role: "user", id: 10 };
const admin = { ...base, role: "admin" };Shallow constraintsSpreads only top-level fields, leaving nested objects pointing to shared references.
const obj = { nested: { val: 1 } };
const copy = { ...obj }; // copy.nested is sharedRest Parameters
Argument gatheringCollects excess function arguments into a single standard array handle.
function sum(...numbers) {
return numbers.reduce((a, b) => a + b, 0);
}Named plus restCombines initial named parameters with trailing rest parameter collections.
function greet(message, ...names) {
console.log(`${message} ${names.join(", ")}`);
}Array destructuringGathers remaining array items into a slice list during value assignment.
const [first, ...rest] = [1, 2, 3, 4];
// first = 1, rest = [2, 3, 4]Object destructuringExtracts target properties while collecting remaining fields in a separate object.
const { password, ...safeData } = user;
// password is isolated, rest goes to safeDataSpread vs Rest
Context directionSpread expands collections out, while rest collects free elements in.
const arr = [1, 2];
const spread = [...arr]; // expands elements
const [...rest] = arr; // collects elementsUsage locationsSpread occurs in literals and calls; rest occurs in signatures and destructuring.
Math.min(...[1, 2]); // spread in call
function test(...args) {} // rest in signatureIn Practice
Updates a specific shopping cart item quantity immutably using object spread syntax to ensure predictable state transitions.
- 01Map through the array of items in the cart object.
- 02Inspect each item to find the target item ID match.
- 03Spread properties of the matching item to construct a new object with updated quantity.
- 04Return unmodified items directly to preserve reference identities.
- 05Spread the root cart properties, overriding the items list and updating timestamps.
function updateItem(cart, itemId, newQty) {
const updatedItems = cart.items.map(item => {
if (item.id !== itemId) return item;
return {
...item,
quantity: newQty
};
});
return {
...cart,
items: updatedItems,
updatedAt: Date.now()
};
}FAQ
Both features use the ... operator but behave oppositely. Spread expands iterables into separate elements in literals or calls. Rest collects multiple separate elements into a single array structure.
Construct a new object by spreading the sources: { ...obj1, ...obj2 }. If properties overlap, values on the right override properties on the left. This operation only copies own properties.
No, spread performs a shallow copy. If the source contains nested objects, their references are copied rather than duplicate objects. Use structuredClone() to perform a deep clone instead.
Declare a rest parameter: function sum(...nums) { ... }. The rest parameter must sit at the end of the argument list. This compiles arguments into a standard iterable array.
Spread only copies own enumerable properties. Non-enumerable properties and properties inherited from prototypes are bypassed. Use standard accessor methods if you need to fetch inherited properties.