Skip to main content

How to Use Destructuring Assignment in JavaScript

Destructuring assignment is one of the most elegant and practical features introduced in ES2015. It provides a concise syntax for extracting values from arrays and properties from objects, assigning them directly to variables in a single statement. Instead of accessing elements one by one with repetitive index lookups or property access, destructuring lets you "unpack" data structures in a way that is readable, compact, and expressive.

Once you learn destructuring, you will use it constantly. It appears in variable declarations, function parameters, loop iterations, import statements, and everywhere else where you need to extract data from structured values. It reduces boilerplate, makes your intent clearer, and pairs beautifully with other modern JavaScript features like the rest operator, default values, and template literals.

This guide covers both array and object destructuring in depth, including default values, renaming, nested patterns, the rest element, practical use in function parameters and loops, and the common syntax pitfall that catches developers off guard.

Array Destructuring: Syntax and Default Values

Array destructuring extracts values from an array (or any iterable) and assigns them to variables based on their position.

Basic Syntax

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

// Without destructuring
let first = colors[0];
let second = colors[1];
let third = colors[2];

// With destructuring
let [a, b, c] = colors;

console.log(a); // "red"
console.log(b); // "green"
console.log(c); // "blue"

The square brackets on the left side are not creating an array. They are the destructuring pattern that tells JavaScript to unpack the right-hand side array into individual variables.

Destructuring Any Iterable

Array destructuring works with any iterable, not just arrays:

// String
let [x, y, z] = "abc";
console.log(x, y, z); // "a" "b" "c"

// Set
let [first, second] = new Set(["hello", "world"]);
console.log(first, second); // "hello" "world"

// Map
let [[key1, val1], [key2, val2]] = new Map([["a", 1], ["b", 2]]);
console.log(key1, val1); // "a" 1
console.log(key2, val2); // "b" 2

// Generator function
function* range(start, end) {
for (let i = start; i <= end; i++) yield i;
}

let [a, b, c] = range(10, 15);
console.log(a, b, c); // 10 11 12

Fewer Variables Than Values

If you declare fewer variables than the array has elements, the extra elements are simply ignored:

let [first, second] = ["apple", "banana", "cherry", "date"];

console.log(first); // "apple"
console.log(second); // "banana"
// "cherry" and "date" are not assigned to anything

More Variables Than Values

If you declare more variables than the array has elements, the extra variables receive undefined:

let [a, b, c] = ["only", "two"];

console.log(a); // "only"
console.log(b); // "two"
console.log(c); // undefined

Default Values

You can provide default values that are used when the extracted value is undefined:

let [a = 1, b = 2, c = 3] = [10, 20];

console.log(a); // 10 (extracted value overrides default)
console.log(b); // 20 (extracted value overrides default)
console.log(c); // 3 (no value at index 2, default is used)

Default values are only applied when the value is strictly undefined, not for other falsy values:

let [a = "default"] = [null];
console.log(a); // null (NOT "default" (null is not undefined))

let [b = "default"] = [0];
console.log(b); // 0 (NOT "default" (0 is not undefined))

let [c = "default"] = [""];
console.log(c); // "" (NOT "default" (empty string is not undefined))

let [d = "default"] = [undefined];
console.log(d); // "default" (undefined triggers the default)

let [e = "default"] = [];
console.log(e); // "default" (missing element is undefined)

Default Values Can Be Expressions

Default values are evaluated lazily, only when needed:

function generateId() {
console.log("Generating ID...");
return Math.random().toString(36).slice(2, 8);
}

let [id = generateId()] = ["existing-id"];
// generateId is NOT called: the value exists
console.log(id); // "existing-id"

let [id2 = generateId()] = [];
// generateId IS called: no value provided
// "Generating ID..."
console.log(id2); // e.g., "k8m3x2"

Destructuring with let, const, and var

Destructuring works with all declaration keywords:

const [a, b] = [1, 2];    // Both are constants
let [x, y] = [3, 4]; // Both are let variables
var [m, n] = [5, 6]; // Both are var variables (avoid in modern code)

Destructuring with Existing Variables (No Declaration)

You can destructure into already-declared variables, but for object destructuring this requires special syntax (covered later):

let a, b;

[a, b] = [1, 2]; // Array destructuring: works fine without parentheses
console.log(a, b); // 1 2

Skipping Elements, Rest Element ...

Skipping Elements

Use commas without variable names to skip elements at specific positions:

let [, , third] = ["apple", "banana", "cherry"];
console.log(third); // "cherry"

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

// Practical: extracting specific parts of a date
let [year, , day] = "2024-01-15".split("-");
console.log(year); // "2024"
console.log(day); // "15"

The Rest Element (...)

The rest element collects all remaining elements into a new array. It must be the last element in the destructuring pattern:

let [first, second, ...rest] = [1, 2, 3, 4, 5, 6];

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

Combining Skip and Rest

let [, second, ...others] = ["skip", "keep", "also", "these", "too"];

console.log(second); // "keep"
console.log(others); // ["also", "these", "too"]

Rest with Empty Remainder

If there are no remaining elements, the rest variable is an empty array (not undefined):

let [a, b, ...rest] = [1, 2];

console.log(a); // 1
console.log(b); // 2
console.log(rest); // [] (empty array, not undefined)

Practical: Head and Tail

A common functional programming pattern:

function processQueue(items) {
if (items.length === 0) return;

let [current, ...remaining] = items;
console.log(`Processing: ${current}`);

if (remaining.length > 0) {
processQueue(remaining); // Recurse with the rest
}
}

processQueue(["task1", "task2", "task3"]);
// Processing: task1
// Processing: task2
// Processing: task3
Rest Must Be Last

The rest element must always be the last item in the destructuring pattern. Placing it anywhere else is a syntax error:

// ❌ SyntaxError: Rest element must be last element
// let [...rest, last] = [1, 2, 3];

// ✅ Correct
let [...all] = [1, 2, 3];
console.log(all); // [1, 2, 3] (effectively a shallow copy)

Swapping Variables with Destructuring

One of the most elegant uses of destructuring is swapping variable values without a temporary variable:

let a = 1;
let b = 2;

// Traditional swap (needs a temp variable)
// let temp = a;
// a = b;
// b = temp;

// Destructuring swap: one line, no temp
[a, b] = [b, a];

console.log(a); // 2
console.log(b); // 1

Rotating Multiple Values

let x = 1, y = 2, z = 3;

[x, y, z] = [y, z, x]; // Rotate left

console.log(x, y, z); // 2 3 1

Practical: Sorting Two Values

let min = 10;
let max = 5;

if (min > max) {
[min, max] = [max, min];
}

console.log(min, max); // 5 10

Object Destructuring: Syntax, Renaming, Default Values

Object destructuring extracts properties from objects based on property names, not position. This is the more commonly used form of destructuring in real-world code.

Basic Syntax

let user = {
name: "Alice",
age: 30,
city: "Rome"
};

// Without destructuring
let name = user.name;
let age = user.age;
let city = user.city;

// With destructuring
let { name, age, city } = user;

console.log(name); // "Alice"
console.log(age); // 30
console.log(city); // "Rome"

The curly braces on the left side are the destructuring pattern, not an object literal. Each identifier inside matches a property name on the right-hand side.

Order Does Not Matter

Unlike array destructuring (position-based), object destructuring is name-based. The order of variables does not need to match the order of properties:

let user = { name: "Alice", age: 30, city: "Rome" };

let { city, name, age } = user; // Different order (still works)

console.log(name); // "Alice"
console.log(age); // 30
console.log(city); // "Rome"

Extracting Only Some Properties

You do not need to destructure all properties:

let user = { name: "Alice", age: 30, city: "Rome", role: "admin" };

let { name, role } = user; // Only extract name and role

console.log(name); // "Alice"
console.log(role); // "admin"
// age and city are not extracted

Renaming Variables

When the property name is not suitable as a variable name (or conflicts with an existing variable), use the propertyName: variableName syntax:

let user = {
name: "Alice",
age: 30,
"home-city": "Rome" // Can't use this as a variable name
};

// Rename during destructuring
let { name: userName, age: userAge, "home-city": homeCity } = user;

console.log(userName); // "Alice"
console.log(userAge); // 30
console.log(homeCity); // "Rome"

// The original property names are NOT created as variables
// console.log(name); // ReferenceError (unless declared elsewhere)

The syntax reads as: "take property name, assign it to variable userName."

Renaming to Avoid Conflicts

let name = "Global Name"; // Already exists

let user = { name: "Alice", age: 30 };

// Rename to avoid shadowing the outer variable
let { name: userName, age } = user;

console.log(name); // "Global Name" (unchanged)
console.log(userName); // "Alice"

Default Values

Default values work the same way as in array destructuring, activated when the property value is undefined or the property does not exist:

let user = { name: "Alice" };

let { name, age = 25, role = "viewer" } = user;

console.log(name); // "Alice"
console.log(age); // 25 (property missing, default used)
console.log(role); // "viewer" (property missing, default used9

Combining Renaming and Defaults

You can rename a variable and provide a default value in the same declaration:

let config = { width: 800 };

let { width: w = 640, height: h = 480, title: t = "Untitled" } = config;

console.log(w); // 800 (from config.width)
console.log(h); // 480 (default (config.height is undefined)9
console.log(t); // "Untitled" (default (config.title is undefined))

The syntax reads as: "take property width, assign it to variable w, default to 640 if undefined."

Rest Properties (...)

The rest syntax collects all remaining (unextracted) properties into a new object:

let user = {
name: "Alice",
age: 30,
city: "Rome",
role: "admin",
active: true
};

let { name, age, ...remaining } = user;

console.log(name); // "Alice"
console.log(age); // 30
console.log(remaining); // { city: "Rome", role: "admin", active: true }

This is extremely useful for separating known properties from the rest:

// Extract specific props, pass the rest through
function Button({ onClick, children, ...htmlProps }) {
// onClick and children are handled specially
// htmlProps contains everything else (className, id, style, etc.)
console.log("Click handler:", onClick);
console.log("Content:", children);
console.log("HTML attributes:", htmlProps);
}

Button({
onClick: () => {},
children: "Click me",
className: "btn-primary",
id: "submit-btn",
disabled: false
});
// Click handler: () => {}
// Content: Click me
// HTML attributes: { className: "btn-primary", id: "submit-btn", disabled: false }

Computed Property Names

You can use computed (dynamic) property names in destructuring:

let key = "name";
let user = { name: "Alice", age: 30 };

let { [key]: value } = user;
console.log(value); // "Alice"

// With a variable key
function extractProperty(obj, prop) {
let { [prop]: value } = obj;
return value;
}

console.log(extractProperty(user, "age")); // 30

Nested Destructuring

When objects or arrays are nested inside each other, destructuring can reach into the nested structures.

Nested Object Destructuring

let user = {
name: "Alice",
address: {
street: "123 Main St",
city: "Rome",
country: "Italy"
},
scores: {
math: 95,
science: 88
}
};

let {
name,
address: { city, country },
scores: { math }
} = user;

console.log(name); // "Alice"
console.log(city); // "Rome"
console.log(country); // "Italy"
console.log(math); // 95

// Note: address and scores are NOT created as variables
// console.log(address); // ReferenceError
// console.log(scores); // ReferenceError

When you write address: { city, country }, the address: part means "look into the address property," and { city, country } extracts from within it. The variable address itself is not created.

If You Need Both the Nested Object and Its Properties

let user = {
name: "Alice",
address: {
city: "Rome",
country: "Italy"
}
};

// Extract both the address object and its properties
let {
name,
address,
address: { city }
} = user;

console.log(name); // "Alice"
console.log(address); // { city: "Rome", country: "Italy" }
console.log(city); // "Rome"

You can reference the same property twice: once to capture it directly, and once to destructure deeper into it.

Nested Array Destructuring

let matrix = [[1, 2], [3, 4], [5, 6]];

let [[a, b], [c, d], [e, f]] = matrix;

console.log(a, b); // 1 2
console.log(c, d); // 3 4
console.log(e, f); // 5 6

Mixed Nesting (Objects Inside Arrays, Arrays Inside Objects)

let response = {
status: 200,
data: {
users: [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" }
]
}
};

let {
status,
data: {
users: [firstUser, secondUser]
}
} = response;

console.log(status); // 200
console.log(firstUser); // { id: 1, name: "Alice" }
console.log(secondUser); // { id: 2, name: "Bob" }

// Even deeper
let {
data: {
users: [{ name: firstName }, { name: secondName }]
}
} = response;

console.log(firstName); // "Alice"
console.log(secondName); // "Bob"

Nested Defaults

Default values work at any nesting level:

let config = {
database: {
host: "localhost"
// port is missing
}
// logging is missing entirely
};

let {
database: { host, port = 5432 },
logging: { level = "info", file = "app.log" } = {} // Default for the whole nested object
} = config;

console.log(host); // "localhost"
console.log(port); // 5432
console.log(level); // "info"
console.log(file); // "app.log"

The = {} after logging is critical. Without it, trying to destructure logging (which is undefined) would throw a TypeError. The default {} provides an empty object to destructure from, and then the inner defaults (level = "info") take effect.

Always Provide Defaults for Optional Nested Objects

When destructuring nested properties that might not exist, always provide a default object (= {}). Without it, destructuring undefined or null throws an error:

let config = {};

// ❌ TypeError: Cannot destructure property 'host' of undefined
// let { server: { host } } = config;

// ✅ Safe with default
let { server: { host = "localhost" } = {} } = config;
console.log(host); // "localhost"

Destructuring in Function Parameters (Smart Parameters Pattern)

Destructuring in function parameters is one of the most impactful practical applications. It makes function signatures clearer and eliminates the need to remember argument order.

Object Destructuring in Parameters

// Without destructuring
function createUser(options) {
let name = options.name;
let age = options.age || 25;
let role = options.role || "viewer";
console.log(`${name}, ${age}, ${role}`);
}

// With destructuring: cleaner, with defaults inline
function createUser({ name, age = 25, role = "viewer" }) {
console.log(`${name}, ${age}, ${role}`);
}

createUser({ name: "Alice", age: 30 });
// "Alice, 30, viewer"

createUser({ name: "Bob", role: "admin" });
// "Bob, 25, admin"

The "Smart Parameters" Pattern

When a function has many optional parameters, passing an object and destructuring it is far cleaner than positional arguments:

// ❌ Positional arguments: hard to remember order, hard to skip
function drawRect(x, y, width, height, color, border, borderRadius, opacity) {
// Which argument is which?
}
drawRect(10, 20, 100, 50, "blue", true, 5, 0.8);
// What do these numbers mean?

// ✅ Named parameters via destructuring: clear and flexible
function drawRect({
x = 0,
y = 0,
width = 100,
height = 100,
color = "black",
border = false,
borderRadius = 0,
opacity = 1.0
} = {}) {
console.log(`Drawing at (${x}, ${y}), ${width}x${height}, ${color}, opacity: ${opacity}`);
}

// Only pass what you need, in any order
drawRect({ width: 200, height: 150, color: "blue" });
// "Drawing at (0, 0), 200x150, blue, opacity: 1"

drawRect({ x: 50, y: 30, opacity: 0.5 });
// "Drawing at (50, 30), 100x100, black, opacity: 0.5"

// All defaults
drawRect();
// "Drawing at (0, 0), 100x100, black, opacity: 1"

Note the = {} at the end of the parameter. This allows calling the function with no arguments at all. Without it, drawRect() would throw because it would try to destructure undefined.

Combining Required and Optional Parameters

function sendEmail(to, { subject = "(no subject)", body = "", cc = [], urgent = false } = {}) {
console.log(`To: ${to}`);
console.log(`Subject: ${subject}`);
console.log(`Body: ${body}`);
console.log(`CC: ${cc.join(", ") || "none"}`);
console.log(`Urgent: ${urgent}`);
}

sendEmail("alice@example.com", {
subject: "Meeting Tomorrow",
body: "Let's meet at 3pm",
urgent: true
});
// To: alice@example.com
// Subject: Meeting Tomorrow
// Body: Let's meet at 3pm
// CC: none
// Urgent: true

// Only the required parameter
sendEmail("bob@example.com");
// To: bob@example.com
// Subject: (no subject)
// Body:
// CC: none
// Urgent: false

Array Destructuring in Parameters

// Destructure array parameter
function getDistance([x1, y1], [x2, y2]) {
return Math.hypot(x2 - x1, y2 - y1);
}

console.log(getDistance([0, 0], [3, 4])); // 5

// With Map.entries()
function processEntry([key, value]) {
console.log(`${key}: ${value}`);
}

let map = new Map([["a", 1], ["b", 2]]);
map.forEach((value, key) => processEntry([key, value]));

Returning Multiple Values with Destructuring

Functions can return arrays or objects, and the caller destructures the result:

// Returning an array
function getMinMax(numbers) {
return [Math.min(...numbers), Math.max(...numbers)];
}

let [min, max] = getMinMax([5, 2, 8, 1, 9, 3]);
console.log(min, max); // 1 9

// Returning an object (more readable for many values)
function parseUrl(url) {
let parsed = new URL(url);
return {
protocol: parsed.protocol,
host: parsed.host,
path: parsed.pathname,
query: parsed.search
};
}

let { protocol, host, path } = parseUrl("https://example.com/page?id=42");
console.log(protocol); // "https:"
console.log(host); // "example.com"
console.log(path); // "/page"

Object return values are more flexible because the caller can extract only what they need and the order does not matter. Array return values are more concise for two or three values.

Destructuring with for...of, Map.entries(), etc.

Destructuring combines beautifully with loops over iterables.

Destructuring in for...of

let users = [
{ name: "Alice", age: 30 },
{ name: "Bob", age: 25 },
{ name: "Charlie", age: 35 }
];

// Destructure each object in the loop
for (let { name, age } of users) {
console.log(`${name} is ${age} years old`);
}
// Alice is 30 years old
// Bob is 25 years old
// Charlie is 35 years old

With Object.entries()

let scores = { Alice: 95, Bob: 88, Charlie: 72 };

for (let [name, score] of Object.entries(scores)) {
console.log(`${name}: ${score}`);
}
// Alice: 95
// Bob: 88
// Charlie: 72

With Map

let userRoles = new Map([
["alice@example.com", "admin"],
["bob@example.com", "editor"],
["charlie@example.com", "viewer"]
]);

for (let [email, role] of userRoles) {
console.log(`${email}${role}`);
}
// alice@example.com → admin
// bob@example.com → editor
// charlie@example.com → viewer

With Map.entries() and Nested Destructuring

let departments = new Map([
["Engineering", { lead: "Alice", size: 15 }],
["Marketing", { lead: "Bob", size: 8 }],
["Design", { lead: "Charlie", size: 5 }]
]);

for (let [dept, { lead, size }] of departments) {
console.log(`${dept}: led by ${lead}, ${size} people`);
}
// Engineering: led by Alice, 15 people
// Marketing: led by Bob, 8 people
// Design: led by Charlie, 5 people

With Array.entries() for Index + Value

let fruits = ["apple", "banana", "cherry"];

for (let [index, fruit] of fruits.entries()) {
console.log(`${index}: ${fruit}`);
}
// 0: apple
// 1: banana
// 2: cherry

In forEach Callbacks

let prices = new Map([
["coffee", 4.50],
["tea", 3.00],
["juice", 5.25]
]);

// Destructuring in the callback parameter
prices.forEach((price, name) => {
console.log(`${name}: $${price.toFixed(2)}`);
});
// coffee: $4.50
// tea: $3.00
// juice: $5.25

// With Object.entries
let config = { host: "localhost", port: 3000, debug: true };

Object.entries(config).forEach(([key, value]) => {
console.log(`${key} = ${value}`);
});
// host = localhost
// port = 3000
// debug = true

In Array Methods (map, filter, etc.)

let pairs = [[1, "one"], [2, "two"], [3, "three"]];

// Destructure in map callback
let formatted = pairs.map(([num, word]) => `${num} = ${word}`);
console.log(formatted); // ["1 = one", "2 = two", "3 = three"]

// Destructure in filter callback
let users = [
{ name: "Alice", active: true },
{ name: "Bob", active: false },
{ name: "Charlie", active: true }
];

let activeNames = users
.filter(({ active }) => active)
.map(({ name }) => name);
console.log(activeNames); // ["Alice", "Charlie"]

Common Mistake: Destructuring Without let/const (Parentheses Required)

When destructuring objects into already-declared variables (without let, const, or var), you encounter a syntax trap that catches many developers.

The Problem

let name, age;

// ❌ SyntaxError: Unexpected token '='
// { name, age } = { name: "Alice", age: 30 };

JavaScript interprets { at the beginning of a statement as the start of a code block, not a destructuring pattern. The parser sees { name, age } and thinks it is a block statement with a label name and a variable age, which makes = { ... } a syntax error.

The Fix: Wrap in Parentheses

let name, age;

// ✅ Parentheses tell JavaScript this is an expression, not a block
({ name, age } = { name: "Alice", age: 30 });

console.log(name); // "Alice"
console.log(age); // 30

The parentheses force JavaScript to interpret the { as the start of an expression (a destructuring assignment) rather than a code block.

This Is Only Needed for Object Destructuring

Array destructuring does not have this problem because [ cannot be confused with a block:

let a, b;

[a, b] = [1, 2]; // ✅ Works fine without parentheses
console.log(a, b); // 1 2

When This Comes Up in Practice

let result = {};

// ❌ Common mistake when updating variables in a loop or condition
// { result.name, result.age } = getUser(); // SyntaxError

// ✅ Correct
let name, age;
({ name, age } = getUser());
result.name = name;
result.age = age;

Another Common Pattern

let config = { width: 100, height: 200 };

// Updating config with new values
let updates = { width: 300, color: "blue" };

// This won't work as expected for overriding:
// ({ width, height } = { ...config, ...updates });

// Usually you'd just use spread:
config = { ...config, ...updates };
console.log(config); // { width: 300, height: 200, color: "blue" }
Remember the Parentheses

When destructuring objects into existing variables (without a declaration keyword), always wrap the entire statement in parentheses: ({ a, b } = obj). Without parentheses, JavaScript interprets the curly braces as a code block and throws a SyntaxError.

Practical Patterns and Real-World Examples

API Response Handling

async function fetchUser(id) {
let response = await fetch(`/api/users/${id}`);
let { status } = response;

if (status !== 200) {
throw new Error(`Failed with status ${status}`);
}

let { name, email, preferences: { theme = "light", language = "en" } = {} } = await response.json();

return { name, email, theme, language };
}

React-Style Props Handling

function UserCard({ name, avatar = "/default-avatar.png", role = "member", ...rest }) {
console.log(`Name: ${name}`);
console.log(`Avatar: ${avatar}`);
console.log(`Role: ${role}`);
console.log(`Other props:`, rest);
}

UserCard({
name: "Alice",
role: "admin",
className: "card-large",
onClick: () => {}
});

Configuration Merging

function initApp({
port = 3000,
host = "localhost",
database: {
url = "mongodb://localhost:27017",
name = "myapp"
} = {},
logging: {
level = "info",
file = null
} = {}
} = {}) {
console.log(`Server: ${host}:${port}`);
console.log(`Database: ${url}/${name}`);
console.log(`Logging: ${level}${file ? `${file}` : ""}`);
}

initApp({
port: 8080,
database: { name: "production" },
logging: { level: "warn", file: "/var/log/app.log" }
});
// Server: localhost:8080
// Database: mongodb://localhost:27017/production
// Logging: warn → /var/log/app.log

initApp(); // All defaults
// Server: localhost:3000
// Database: mongodb://localhost:27017/myapp
// Logging: info

Module Imports (Destructuring Syntax)

While not technically the same mechanism, ES module imports use a syntax that looks like object destructuring:

// Named imports look like object destructuring
import { useState, useEffect, useRef } from "react";

// This is similar in concept to:
// const { useState, useEffect, useRef } = require("react");

Summary

  • Array destructuring extracts values by position using [a, b, c] = array. It works with any iterable, not just arrays.
  • Object destructuring extracts values by property name using { name, age } = obj. Order does not matter.
  • Default values (= defaultValue) are used when the destructured value is undefined or missing. They are evaluated lazily.
  • Skipping elements in arrays is done with empty commas: [, , third] = arr.
  • The rest element (...rest) collects remaining items into an array (for arrays) or a new object (for objects). It must be the last item.
  • Renaming in object destructuring uses { propertyName: variableName } syntax. Combine with defaults: { prop: variable = default }.
  • Nested destructuring reaches into deeply nested structures. Always provide default objects (= {}) for optional nested paths to prevent TypeError.
  • Function parameters are the most impactful use case. The "smart parameters" pattern (function f({ opt1, opt2 } = {})) creates readable APIs with named, optional parameters and inline defaults.
  • Destructuring works beautifully with for...of, Object.entries(), Map iteration, and array method callbacks for clean, expressive loops.
  • Swapping variables is a one-liner: [a, b] = [b, a].
  • When destructuring objects without a declaration keyword, wrap the statement in parentheses: ({ a, b } = obj). Without them, JavaScript misinterprets the { as a code block.

Table of Contents