Destructuring Spread and Rest
Unpack values with destructuring, then expand or gather them using the spread and rest operators.
TL;DR
- Extract object properties into variables with curly brace syntax.
- Extract array elements into variables with square bracket syntax.
- Use default values when properties or elements are missing.
Object Destructuring
Basic extractionExtract properties from an object into separate variables.
const user = { name: "Alice", age: 30 };
const { name, age } = user;
console.log(name); // "Alice"Exact key matchProperty names must match the object keys exactly.
const { name, email } = user;
// name is available, but email is undefinedRenamingUse shorter or clearer variable names with renaming.
const { name: userName, age: userAge } = user;Nested objectsDestructure nested objects by continuing the pattern.
const user = { profile: { name: "Alice" } };
const { profile: { name } } = user;Array Destructuring
Position-based extractionExtract array elements into separate variables by position.
const colors = ["red", "green", "blue"];
const [first, second, third] = colors;
console.log(first); // "red"Skipping elementsSkip elements by leaving the position empty.
const [first, , third] = colors;
// second is not assignedRest syntaxUse rest syntax to capture remaining elements.
const [first, ...rest] = colors;
// first = "red", rest = ["green", "blue"]Swapping variablesSwap variables without a temporary variable.
let x = 1, y = 2;
[x, y] = [y, x]; // x = 2, y = 1Default Values & Spread with Arrays
Basic defaultsProvide default values for properties that might be missing.
const { name = "Guest", email = "no-email" } = {};
console.log(name); // "Guest"Undefined onlyDefaults are used only if the value is undefined, not falsy.
const { count = 0 } = { count: false };
// count = false, not 0Defaults in parametersUse defaults with function parameters for required values.
function greet({ name = "Guest" } = {}) {
console.log(`Hello ${name}`);
}
greet(); // "Hello Guest"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 function call parameters.
const numbers = [5, 10, 3];
Math.max(...numbers); // 10Spread 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 safeDataTips
- Use destructuring in function parameters to document what properties a function expects, making code more readable and self-documenting.
- Combine destructuring with rest syntax to pull out a few named values while collecting the remaining properties into one object.
- Rename destructured variables to avoid naming collisions when two objects in the same scope share a property name.
Warnings
- Destructuring doesn't create new properties on objects — it just assigns values to variables in the local scope.
- Destructuring a null or undefined value throws a TypeError immediately, so guard against missing data before destructuring it.
- Default values only apply when a property is undefined, so a falsy value like false or 0 still wins.
In Practice
Nested destructuring, renaming, and defaults pull exactly the fields needed from a server response in one expression.
- The pattern reaches into data, user, and settings without temporary variables.
- name: userName renames the property, while role = 'guest' supplies a fallback.
- theme = 'light' provides a default when settings is missing.
- ...meta collects top-level fields not already extracted.
const response = await fetch('/api/user').then(r => r.json());
const { data: { user: { name: userName, role = 'guest' }, settings: { theme = 'light' } = {} }, ...meta } = response;
console.log(userName, role, theme, meta);FAQ
Use the colon syntax: const { name: firstName } = user assigns the name property to a variable called firstName. This lets you avoid naming conflicts or clarify intent without modifying the original object.
Yes — chain the syntax: const { address: { city } } = user extracts city from a nested object. Be careful with deep nesting. It throws if an intermediate property is null or undefined.
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.