Skip to main content

Destructuring & Rest/Spread Syntax

ES6 introduced Destructuring assignment and the Rest/Spread (...) operator, revolutionizing how developers extract, unpack, transform, and merge data structures in JavaScript with clean, declarative syntax.

Destructuring Assignment

Destructuring allows you to unpack values from arrays or properties from objects directly into distinct variables.

1. Object Destructuring

Object destructuring extracts values using property key names:

const user = {
id: 101,
username: "alex_dev",
email: "alex@example.com",
profile: { role: "admin" }
};

// Basic extraction
const { username, email } = user;

// Renaming variables and assigning default values
const { id: userId, isVerified = false } = user;

// Nested object destructuring
const { profile: { role } } = user;

console.log(username, userId, isVerified, role);
// Output: "alex_dev", 101, false, "admin"

2. Array Destructuring

Array destructuring extracts elements based on ordered position:

const coordinates = [37.7749, -122.4194, 15]; // [lat, lng, altitude]

// Unpacking by position
const [lat, lng] = coordinates;

// Skipping elements with empty commas
const [, longitude, altitude = 0] = coordinates;

// Swapping variables without temporary variables
let a = 1;
let b = 2;
[a, b] = [b, a]; // a = 2, b = 1

Rest vs. Spread Operator (...)

Although both use the ... syntax, their purpose depends entirely on where they are used:

  • Rest Operator: Gathers multiple individual elements into a single array or object.
  • Spread Operator: Expands an array or iterable into individual elements or object properties.
Rest vs. Spread Spectrum
┌──────────────────────────────────────────────────────────┐
│ REST: Gather elements into an array │
│ function sum(...numbers) { ... } │
├──────────────────────────────────────────────────────────┤
│ SPREAD: Expand iterable into discrete elements │
│ const Combined = [...arr1, ...arr2]; │
└──────────────────────────────────────────────────────────┘

The Rest Operator (...)

Collects remaining items during function parameter definitions or destructuring assignments:

// Rest in Function Parameters
function calculateTotal(taxRate, ...prices) {
const sum = prices.reduce((acc, curr) => acc + curr, 0);
return sum * (1 + taxRate);
}

// Rest in Object Destructuring
const product = { id: 1, name: "Keyboard", price: 99, inStock: true };
const { id, name, ...metadata } = product;

console.log(metadata); // { price: 99, inStock: true }

The Spread Operator (...)

Unpacks iterables or object key-value pairs into new structures:

// Array Spreading & Concatenation
const frontend = ["React", "Vue"];
const backend = ["Node", "Express"];
const stack = [...frontend, "TypeScript", ...backend];

// Object Spreading & Merging
const defaultSettings = { theme: "light", notifications: true };
const userSettings = { theme: "dark" };

// Deep properties are overwritten by right-most spread objects
const currentConfig = { ...defaultSettings, ...userSettings };
// { theme: "dark", notifications: true }

Shallow Copy Warning

Spreading arrays or objects creates a shallow copy. Nested object references remain shared across copies. Use structuredClone() or libraries like Lodash for deep copying.

Interactive Playground: Destructuring & Immutable Updates

Experiment with updating nested object states immutably using object destructuring and spread syntax:

destructuring-immutable-updates.js
JavaScript Runtime
Console Output

Best Practices

  1. Use Destructuring in Function Parameters: Cleanly extract options or props directly in the parameter signature: function Profile({ name, age = 18 }).
  2. Preserve Immutability with Spread: Use the spread operator instead of mutating existing arrays with push() or objects with direct property assignment.
  3. Provide Fallbacks for Safety: Always assign default values during destructuring to prevent runtime TypeError issues on undefined properties.

Knowledge Check

Exercise Requirements:

Write a function formatUserResponse(response) that uses destructuring, default values, and the rest operator to extract id, name, and collect all remaining user settings into a single preferences object.

solution.js
function formatUserResponse(response) {
const {
id = 0,
name = "Anonymous",
status,
...preferences
} = response;

return {
id,
name,
preferences
};
}

Next Up

Now that you have mastered destructuring and rest/spread syntax, proceed to Modules and ES6 Imports/Exports!