Home
 › Learn
 › JavaScript

Learn JavaScript Destructuring and Spread Operators

A comprehensive guide to destructuring assignment, spread operators, and rest parameters for writing cleaner, more concise JavaScript code.

Updated At: December 2021
Learn JavaScript Destructuring and Spread Operators

What is Destructuring?

Destructuring is a convenient way to extract values from arrays or properties from objects and assign them to variables in a single statement. It reduces boilerplate and makes code more readable.

FeatureUse CaseExample
Array DestructuringExtract array elementsconst [a, b] = arr;
Object DestructuringExtract object propertiesconst { name, age } = obj;
Default ValuesHandle missing dataconst { x = 0 } = obj;
Rest in DestructuringCollect remaining itemsconst [first, ...rest] = arr;
Spread OperatorExpand arrays/objectsconst merged = [...arr1, ...arr2];
Rest ParametersCapture function argumentsfunction fn(...args) {}
RenamingAssign different namesconst { name: n } = obj;

Destructuring and spread/rest operators are essential modern JavaScript features that make code cleaner, more concise, and easier to maintain!

Array Destructuring

Basic Array Destructuring

Extract elements from an array into separate variables.

const colors = ["red", "green", "blue"];

// Without destructuring
const first = colors[0];
const second = colors[1];

// With destructuring
const [firstColor, secondColor] = colors;
console.log(firstColor);  // "red"
console.log(secondColor); // "green"


⁠Skipping Elements

Use commas to skip unwanted elements.

const [red, , blue] = ["red", "green", "blue"];
console.log(red);  // "red"
console.log(blue); // "blue"


⁠Default Values

Assign default values when elements might be undefined.

const [a, b, c = "default"] = [1, 2];
console.log(a); // 1
console.log(b); // 2
console.log(c); // "default"


⁠Rest Element in Arrays

Use the rest operator (...) to collect remaining elements into an array.

const [first, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(rest);  // [2, 3, 4, 5]


⁠Swapping Variables

Destructuring makes variable swapping simple.

let x = 10;
let y = 20;

[x, y] = [y, x];
console.log(x); // 20
console.log(y); // 10


⁠Destructuring in Function Parameters

Extract array elements directly in function parameters.

function printCoordinates([x, y]) {
  console.log(`X: ${x}, Y: ${y}`);
}

printCoordinates([5, 10]); // "X: 5, Y: 10"

Object Destructuring

Basic Object Destructuring

Extract properties from an object into variables.

const person = {
  name: "Alice",
  age: 30,
  city: "London"
};

// Without destructuring
const name = person.name;
const age = person.age;

// With destructuring
const { name, age } = person;
console.log(name); // "Alice"
console.log(age);  // 30


⁠Renaming Properties

Assign different variable names to properties.

const person = { firstName: "Bob", lastName: "Smith" };
const { firstName: fName, lastName: lName } = person;

console.log(fName); // "Bob"
console.log(lName); // "Smith"


⁠Default Values

Set default values for missing properties.

const person = { name: "Carol" };
const { name, age = 25, city = "Unknown" } = person;

console.log(name); // "Carol"
console.log(age);  // 25
console.log(city); // "Unknown"


⁠Rest Properties

Collect remaining properties into a new object.

const user = {
  id: 1,
  name: "David",
  email: "david@example.com",
  role: "admin"
};

const { id, name, ...metadata } = user;
console.log(id);       // 1
console.log(name);     // "David"
console.log(metadata); // { email: "david@example.com", role: "admin" }


⁠Nested Object Destructuring

Extract values from nested objects.

const person = {
  name: "Eve",
  address: {
    city: "Paris",
    country: "France"
  }
};

const { name, address: { city, country } } = person;
console.log(name);    // "Eve"
console.log(city);    // "Paris"
console.log(country); // "France"


⁠Destructuring in Function Parameters

Extract object properties directly in function parameters.

function displayUser({ name, age, email = "no-email" }) {
  console.log(`${name}, ${age}, ${email}`);
}

displayUser({ name: "Frank", age: 35 });
// "Frank, 35, no-email"


⁠Destructuring with Dynamic Keys

Use computed property names (advanced pattern).

const obj = { a: 1, b: 2 };
const key = "a";
const { [key]: value } = obj;
console.log(value); // 1


⁠The Spread Operator (...)

The spread operator expands iterables (arrays, strings, objects) into individual elements.

Spreading Arrays

Combine multiple arrays into one.

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];

const combined = [...arr1, ...arr2];
console.log(combined); // [1, 2, 3, 4, 5, 6]


⁠Insert elements at specific positions.

const arr = [1, 5];
const withInserted = [1, 2, 3, ...arr, 4];
console.log(withInserted); // [1, 2, 3, 1, 5, 4]


⁠Copying Arrays

Create a shallow copy of an array.

const original = [1, 2, 3];
const copy = [...original];

copy.push(4);
console.log(original); // [1, 2, 3]
console.log(copy);     // [1, 2, 3, 4]


⁠Spreading Strings

Convert a string into an array of characters.

const str = "hello";
const chars = [...str];
console.log(chars); // ["h", "e", "l", "l", "o"]


⁠Spreading Objects

Merge multiple objects.

const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };

const merged = { ...obj1, ...obj2 };
console.log(merged); // { a: 1, b: 2, c: 3, d: 4 }


⁠Overwrite properties with later values.

const defaults = { theme: "light", fontSize: 14 };
const userSettings = { theme: "dark" };

const finalSettings = { ...defaults, ...userSettings };
console.log(finalSettings); // { theme: "dark", fontSize: 14 }


⁠Create a shallow copy of an object.

const original = { name: "Grace", age: 28 };
const copy = { ...original };

copy.age = 30;
console.log(original.age); // 28
console.log(copy.age);     // 30


⁠Spreading Function Arguments

Pass array elements as individual arguments to a function.

function sum(a, b, c) {
  return a + b + c;
}

const numbers = [1, 2, 3];
console.log(sum(...numbers)); // 6


⁠The Rest Operator (...)

The rest operator collects multiple elements into a single variable (typically an array or object).


Rest Parameters in Functions

Capture remaining arguments as an array.

function greet(greeting, ...names) {
  names.forEach(name => console.log(`${greeting}, ${name}!`));
}

greet("Hello", "Alice", "Bob", "Carol");
// "Hello, Alice!"
// "Hello, Bob!"
// "Hello, Carol!"

Rest in Array Destructuring

Collect remaining elements.

const [first, second, ...rest] = [10, 20, 30, 40, 50];
console.log(first); // 10
console.log(second); // 20
console.log(rest);  // [30, 40, 50]


⁠Rest in Object Destructuring

Collect remaining properties.

const { id, name, ...details } = {
  id: 1,
  name: "Henry",
  email: "henry@example.com",
  phone: "555-1234"
};

console.log(id);      // 1
console.log(name);    // "Henry"
console.log(details); // { email: "henry@example.com", phone: "555-1234" }


⁠Practical Examples

Extract Function Parameters

function createUser(userData) {
  const { name, email, ...profile } = userData;
  console.log(`User: ${name}`);
  console.log(`Email: ${email}`);
  console.log(`Profile data:`, profile);
}

createUser({
  name: "Iris",
  email: "iris@example.com",
  age: 26,
  country: "Germany"
});
// User: Iris
// Email: iris@example.com
// Profile data: { age: 26, country: "Germany" }


⁠API Response Handling

async function fetchUserAndPosts(userId) {
  try {
    const response = await fetch(`/api/users/${userId}`);
    const { user: { name, email }, posts = [] } = await response.json();
    
    console.log(`${name} (${email}) has ${posts.length} posts`);
  } catch (error) {
    console.log("Error:", error.message);
  }
}


⁠Array Filtering with Destructuring

const users = [
  { id: 1, name: "Jack", active: true },
  { id: 2, name: "Kate", active: false },
  { id: 3, name: "Liam", active: true }
];

const activeUsers = users
  .filter(({ active }) => active)
  .map(({ id, name }) => ({ id, name }));

console.log(activeUsers);
// [{ id: 1, name: "Jack" }, { id: 3, name: "Liam" }]


⁠Function Composition with Spread

function multiply(a, b, c) {
  return a * b * c;
}

function applyMultiply(...args) {
  return multiply(...args);
}

console.log(applyMultiply(2, 3, 4)); // 24


⁠Removing Duplicates from Array

const numbers = [1, 2, 2, 3, 3, 3, 4];
const unique = [...new Set(numbers)];
console.log(unique); // [1, 2, 3, 4]


⁠Cloning Nested Objects (Shallow)

const original = {
  name: "Monica",
  skills: ["JavaScript", "React"]
};

const cloned = { ...original };
cloned.skills.push("Node.js");

console.log(original.skills); // ["JavaScript", "React", "Node.js"] (shared reference!)


⁠Creating New Objects Without Mutation

const user = { name: "Noah", age: 32, role: "user" };

// Promote user to admin without mutating original
const admin = { ...user, role: "admin" };

console.log(user);  // { name: "Noah", age: 32, role: "user" }
console.log(admin); // { name: "Noah", age: 32, role: "admin" }  


⁠Combining Destructuring and Rest

const [head, ...tail] = [1, 2, 3, 4, 5];
const { name, ...rest } = { name: "Olivia", city: "NYC", age: 29 };

console.log(head);   // 1
console.log(tail);   // [2, 3, 4, 5]
console.log(name);   // "Olivia"
console.log(rest);   // { city: "NYC", age: 29 }


Common Pitfalls

Shallow Copy Limitation

Spreading only creates a shallow copy — nested objects are still shared.

const original = { user: { name: "Peter" } };
const copy = { ...original };

copy.user.name = "Paul";
console.log(original.user.name); // "Paul" (shared reference!)


Solution: Use structuredClone() for deep copies.

const deepCopy = structuredClone(original);
deepCopy.user.name = "Paul";
console.log(original.user.name); // "Peter" (unchanged)


⁠Rest Must Be Last

The rest operator must be the final element in destructuring.

// ✗ Invalid
const { ...rest, name } = obj;

// ✓ Valid
const { name, ...rest } = obj;


⁠Order Matters in Rest

Only one rest element is allowed per destructuring.

// ✗ Invalid
const [a, ...b, ...c] = [1, 2, 3];

// ✓ Valid
const [a, ...rest] = [1, 2, 3];


⁠Best Practices

  1. Use destructuring for cleaner code — Extract needed values upfront.

  2. Provide sensible defaults — Use = defaultValue syntax.

  3. Rename properties when needed — Use { prop: newName } for clarity.

  4. Combine with rest operator — Separate specific values from the rest.

  5. Be aware of shallow copying — Use structuredClone() for deep copies.

  6. Use spread in function calls — Avoid manual array unpacking.

  7. Prefer destructuring in parameters — Makes function contracts clearer.

  8. Keep destructuring readable — Don't over-nest or create overly complex patterns.

  9. Use rest parameters — Instead of arguments object in modern JavaScript.

  10. Comment complex destructuring — Help future readers understand intent.

JavaScript

    React

      NextJS

        HTML

          CSS

            Sign up for our newsletter.

            Copyright © theHardCoder 2021 - 2025