JavaScript Destructuring

Destructuring is one of the most used ES6 features. It unpacks arrays and objects into variables in a single clean expression - essential for modern JavaScript and frameworks like React.

Intermediate 9 min read 10 examples

Array Destructuring

Array destructuring extracts values by position. You can skip elements, collect the rest, and swap variables without a temp variable.

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

// Basic array destructuring
const [first, second] = colors;
console.log(first);  // "red"
console.log(second); // "green"

// Skip elements with commas
const [, , third] = colors;
console.log(third);  // "blue"

// Swap variables - no temp variable needed!
let a = 1, b = 2;
[a, b] = [b, a];
console.log(a, b); // 2 1

// From function return values
function getMinMax(arr) {
    return [Math.min(...arr), Math.max(...arr)];
}
const [min, max] = getMinMax([3, 1, 4, 1, 5, 9]);
console.log(min, max); // 1 9

// Nested array destructuring
const matrix = [[1, 2], [3, 4]];
const [[a1, b1], [c1, d1]] = matrix;
console.log(a1, b1, c1, d1); // 1 2 3 4

Object Destructuring

Object destructuring extracts properties by name. Order does not matter - only the property name matters.

JavaScript
const user = {
    name: "Alice",
    age: 28,
    email: "alice@example.com",
    city: "London"
};

// Basic object destructuring
const { name, age } = user;
console.log(name); // "Alice"
console.log(age);  // 28

// Order does not matter (unlike array destructuring)
const { city, name: n2 } = user;
console.log(city); // "London"

// Non-existent properties get undefined
const { phone } = user;
console.log(phone); // undefined

// Destructure from function return
function getUserProfile(id) {
    return { name: "Bob", age: 25, role: "admin" };
}
const { name: userName, role } = getUserProfile(42);
console.log(userName, role); // "Bob" "admin"

Default Values

Default values are used when the destructured value is undefined. They do NOT apply to null or any other falsy value.

JavaScript
// Object destructuring with defaults
const config = { host: "localhost" };
const { host, port = 3000, ssl = false } = config;
console.log(host, port, ssl); // "localhost" 3000 false

// Default only applies for undefined
const { host: h2, port: p2 = 8080 } = { host: "api.example.com", port: null };
console.log(p2); // null (null !== undefined - default does NOT apply!)

// Array destructuring with defaults
const [x = 10, y = 20, z = 30] = [1, 2];
console.log(x, y, z); // 1 2 30 (z uses default)

// Combine rename and default
const { name: displayName = "Anonymous" } = {};
console.log(displayName); // "Anonymous"

Renaming Variables

JavaScript
const user = { name: "Alice", id: 1 };
const post = { name: "Hello World", id: 42 };

// Rename to avoid collision when destructuring two objects
const { name: userName, id: userId } = user;
const { name: postTitle, id: postId } = post;

console.log(userName, userId);    // "Alice" 1
console.log(postTitle, postId);   // "Hello World" 42

// Rename with default value
const settings = {};
const { theme: appTheme = "light", lang: appLang = "en" } = settings;
console.log(appTheme, appLang); // "light" "en"

// API response often uses snake_case - rename to camelCase
const apiResponse = { user_name: "alice", is_admin: true };
const { user_name: username, is_admin: isAdmin } = apiResponse;
console.log(username, isAdmin); // "alice" true

Nested Destructuring

JavaScript
const user = {
    name: "Alice",
    address: {
        city: "London",
        zip: "SW1A 1AA",
        country: {
            code: "GB",
            name: "United Kingdom"
        }
    },
    skills: ["JavaScript", "Python", "Go"]
};

// Nested object destructuring
const {
    name,
    address: { city, zip },
    address: { country: { code } }
} = user;
console.log(name, city, zip, code); // "Alice" "London" "SW1A 1AA" "GB"

// Mixed: array inside object, object inside array
const { skills: [primarySkill, ...otherSkills] } = user;
console.log(primarySkill);  // "JavaScript"
console.log(otherSkills);   // ["Python", "Go"]

// Nested array with defaults
const data = { coords: [10, 20] };
const { coords: [lat = 0, lng = 0, alt = 0] } = data;
console.log(lat, lng, alt); // 10 20 0

Rest in Destructuring

JavaScript
// Array rest - collects remaining elements
const [head, ...tail] = [1, 2, 3, 4, 5];
console.log(head); // 1
console.log(tail); // [2, 3, 4, 5]

const [first, second, ...rest] = "hello".split("");
console.log(first, second, rest); // "h" "e" ["l","l","o"]

// Object rest - collects remaining properties
const user = { name: "Alice", age: 28, city: "London", role: "admin" };

const { name, age, ...otherProps } = user;
console.log(name, age);   // "Alice" 28
console.log(otherProps);  // { city: "London", role: "admin" }

// Useful for "omitting" properties (create object without a field)
const { password, ...safeUser } = { name: "Alice", email: "a@b.com", password: "secret" };
console.log(safeUser); // { name: "Alice", email: "a@b.com" } - no password!

Function Parameters

Destructuring in function parameters is one of the most practical uses - it gives functions named parameters with optional defaults.

JavaScript
// Without destructuring - verbose
function createUser1(options) {
    const name  = options.name;
    const email = options.email;
    const role  = options.role || "user";
    // ...
}

// With destructuring - clean and self-documenting
function createUser({ name, email, role = "user", active = true } = {}) {
    return { name, email, role, active, createdAt: new Date() };
}

console.log(createUser({ name: "Alice", email: "a@b.com" }));
// { name: "Alice", email: "a@b.com", role: "user", active: true, ... }

// Array parameter destructuring
function swap([a, b]) {
    return [b, a];
}
console.log(swap([1, 2])); // [2, 1]

// In forEach with entries
const users = [
    { name: "Alice", role: "admin" },
    { name: "Bob",   role: "user" },
];

users.forEach(({ name, role }, index) => {
    console.log(`${index}: ${name} (${role})`);
});
// 0: Alice (admin)
// 1: Bob (user)

Common Patterns

JavaScript
// 1. Unpack useState in React (array destructuring)
const [count, setCount] = useState(0);

// 2. Unpack useRouter in Next.js (object destructuring)
const { pathname, query, push } = useRouter();

// 3. Unpack API response
const { data: { users, total }, status } = await fetchUsers();

// 4. for...of with Object.entries
const scores = { Alice: 95, Bob: 87, Carol: 92 };
for (const [name, score] of Object.entries(scores)) {
    console.log(`${name}: ${score}`);
}

// 5. Import { } is destructuring-like syntax (but not actual destructuring)
import { useState, useEffect } from "react";

// 6. Default export parameter pattern
function App({ title = "My App", theme = "light" } = {}) {
    // ...
}

// 7. Immutable update with rest
const updateUser = (user, updates) => ({ ...user, ...updates });
const alice = { name: "Alice", age: 28, city: "London" };
const updated = updateUser(alice, { age: 29 });
console.log(updated); // { name: "Alice", age: 29, city: "London" }

Frequently Asked Questions

Destructuring is a syntax that unpacks values from arrays or properties from objects into separate variables in a single statement. Instead of writing const name = user.name; const age = user.age;, you write const { name, age } = user;. It makes code more concise and readable, especially when working with function parameters and API responses.

The variable gets the value undefined. You can prevent this by providing a default value: const { name = "Guest" } = user - if user.name is undefined, name is "Guest". Default values only apply when the value is undefined, not when it is null or false.

Yes. Use a colon after the property name: const { name: userName } = user creates a variable called userName with the value of user.name. You can combine renaming and defaults: const { name: userName = "Guest" } = user. This is very useful when two objects have the same property names and you need both in the same scope.

The rest element (...) collects all remaining items not already destructured. For arrays: const [first, ...rest] = [1,2,3,4] gives first = 1 and rest = [2,3,4]. For objects: const { a, ...others } = obj gives a and others containing all other properties. The rest element must always be last.