Array Destructuring
Array destructuring extracts values by position. The left-hand side uses square brackets to mirror the array structure.
// Basic array destructuring
const rgb = [255, 128, 0];
const [red, green, blue] = rgb;
console.log(red, green, blue); // 255 128 0
// Skip elements with commas
const [first, , third] = [10, 20, 30];
console.log(first, third); // 10 30
// Rest element β collects remaining items
const [head, ...tail] = [1, 2, 3, 4, 5];
console.log(head); // 1
console.log(tail); // [2, 3, 4, 5]
// Default values β used when the value is undefined
const [a = 0, b = 0, c = 0] = [1, 2];
console.log(a, b, c); // 1 2 0
// Swap variables β no temp variable needed!
let x = 1, y = 2;
[x, y] = [y, x];
console.log(x, y); // 2 1
// Nested array destructuring
const matrix = [[1, 2], [3, 4]];
const [[r1c1, r1c2], [r2c1]] = matrix;
console.log(r1c1, r1c2, r2c1); // 1 2 3
255 128 0 10 30 1 [2, 3, 4, 5] 1 2 0 2 1 1 2 3
Object Destructuring
Object destructuring extracts values by key name. The left-hand side uses curly braces and must match property names (unless renamed).
const user = {
id: 42,
name: 'Alice',
role: 'admin',
email: 'alice@example.com'
};
// Basic object destructuring
const { name, role } = user;
console.log(name, role); // Alice admin
// Rename while destructuring (key: newName)
const { name: userName, email: userEmail } = user;
console.log(userName, userEmail); // Alice alice@example.com
// Default values
const { name: n, country = 'Unknown' } = user;
console.log(n, country); // Alice Unknown
// Rest in object destructuring
const { id, ...rest } = user;
console.log(id); // 42
console.log(rest); // { name: 'Alice', role: 'admin', email: '...' }
// Nested object destructuring
const config = {
server: { host: 'localhost', port: 3000 },
db: { name: 'mydb' }
};
const { server: { host, port }, db: { name: dbName } } = config;
console.log(host, port, dbName); // localhost 3000 mydb
Function Parameter Destructuring
Destructuring in function parameters makes it immediately clear which properties of an argument object are used β and can provide defaults inline.
// Without destructuring (old way)
function greetOld(user) {
return `Hello, ${user.name}! Role: ${user.role}`;
}
// With parameter destructuring
function greet({ name, role = 'guest' }) {
return `Hello, ${name}! Role: ${role}`;
}
console.log(greet({ name: 'Bob' })); // Hello, Bob! Role: guest
console.log(greet({ name: 'Alice', role: 'admin' })); // Hello, Alice! Role: admin
// Array parameter destructuring
function getFirstAndLast([first, ...rest]) {
return { first, last: rest[rest.length - 1] };
}
console.log(getFirstAndLast([10, 20, 30, 40]));
// { first: 10, last: 40 }
// Multiple return values (via array)
function minMax(arr) {
return [Math.min(...arr), Math.max(...arr)];
}
const [min, max] = minMax([3, 1, 4, 1, 5, 9, 2]);
console.log(min, max); // 1 9
// Default entire options object
function createServer({ host = 'localhost', port = 3000, debug = false } = {}) {
return `${host}:${port} (debug: ${debug})`;
}
console.log(createServer()); // localhost:3000 (debug: false)
console.log(createServer({ port: 8080 })); // localhost:8080 (debug: false)
When a function accepts an options object, add = {} as the default for the entire parameter. This lets callers omit the argument entirely: createServer() rather than createServer({}).
Destructuring in for...of Loops
const users = [
{ name: 'Alice', age: 28 },
{ name: 'Bob', age: 34 },
{ name: 'Carol', age: 22 }
];
// Destructure each iteration
for (const { name, age } of users) {
console.log(`${name} is ${age}`);
}
// Object.entries with destructuring
const scores = { Alice: 95, Bob: 82, Carol: 88 };
for (const [person, score] of Object.entries(scores)) {
console.log(`${person}: ${score}`);
}
// Map iteration with destructuring
const map = new Map([['a', 1], ['b', 2], ['c', 3]]);
for (const [key, value] of map) {
console.log(key, '->', value);
}
Practical Patterns
// 1. Unpacking API responses
async function fetchUser(id) {
const response = await fetch(`/api/users/${id}`);
const { data: { name, email, avatar }, status } = await response.json();
return { name, email, avatar, status };
}
// 2. React props destructuring (common pattern)
function UserCard({ name, avatar = '/default.png', role = 'user', onClick }) {
return `${avatar} ${name} (${role})`;
}
// 3. Mixed array/object destructuring
const [{ name: firstName }, { name: secondName }] = [
{ name: 'Alice', age: 28 },
{ name: 'Bob', age: 34 }
];
console.log(firstName, secondName); // Alice Bob
// 4. Rename with defaults
const { width: w = 800, height: h = 600 } = { width: 1024 };
console.log(w, h); // 1024 600
// 5. Import-style destructuring
const { PI, sqrt, abs } = Math;
console.log(PI, sqrt(16), abs(-5)); // 3.14159... 4 5
Common Mistakes
When destructuring outside of a declaration (const/let/var), you must wrap the statement in parentheses to avoid JavaScript parsing the opening { as a block: ({ name } = obj) not { name } = obj.
| Mistake | Problem | Fix |
|---|---|---|
const { name } = null | TypeError: cannot destructure null | Guard: const { name } = user ?? {} |
const [a] = undefined | TypeError: undefined is not iterable | Guard: const [a] = arr ?? [] |
{ a } = obj as statement | SyntaxError (block parsed) | Wrap: ({ a } = obj) |
| Deeply nested without defaults | TypeError on missing intermediate | Add defaults at each nesting level |
ποΈ Practical Exercise
Given the API response object below, use a single destructuring statement to extract: the user's full name, their city, the first tag, and the total follower count (with a default of 0 if missing).
const response = {
user: { fullName: 'Alice Chen', location: { city: 'Singapore' } },
tags: ['javascript', 'react', 'nodejs'],
stats: { posts: 42 }
};
π₯ Challenge Exercise
Write a function pick(obj, keys) that uses destructuring and rest parameters to return a new object containing only the listed keys from the original. Then write omit(obj, keys) that returns a new object with those keys removed. Do not use any library β implement both in under 5 lines each.
Destructuring Beyond the Basics
Destructuring pulls values out of arrays and objects in one line. The real power shows up with defaults, renaming, and nesting β patterns you'll see in every modern codebase and framework API.
// Object: rename + default in one shot
const { name: userName, role = "guest" } = user;
// Array: skip items, grab the rest
const [first, , third, ...others] = [1, 2, 3, 4, 5];
// Nested β reach deep in one statement
const { address: { city } } = person;
// Swap without a temp variable
let a = 1, b = 2;
[a, b] = [b, a]; // a=2, b=1
Where it shines: function parameters
// Named options with defaults β order-free, self-documenting
function createUser({ name, admin = false } = {}) {
return `${name} (${admin ? "admin" : "user"})`;
}
createUser({ name: "Ann", admin: true });
The = {} after the destructured parameter matters: it lets someone call createUser() with no argument at all instead of crashing on "cannot destructure undefined."
π Summary
- Array destructuring extracts by position; object destructuring extracts by key name.
- Use a comma to skip elements in array destructuring:
const [a, , c] = arr. - Rename with
{ key: newName }and provide defaults with{ key = default }. - The rest operator (
...) collects remaining elements into a new array or object. - Swap variables without a temp variable:
[a, b] = [b, a]. - Destructure function parameters to make APIs self-documenting.
- Guard against
null/undefinedsources with the nullish coalescing operator.
Interview Questions
- How do you swap two variables using destructuring?
- What is the difference between array and object destructuring?
- How do you provide default values in destructuring?
- How do you rename a property while destructuring an object?
- What happens when you destructure a property that does not exist?
- How does rest (
...) work in destructuring vs spread?
Related Topics
FAQ
No. Destructuring only reads values from the source. The original object or array is untouched. The destructured variables are new bindings that hold the extracted values.
Yes. This is one of the most common uses. Functions can return an array or object, and you destructure immediately: const [min, max] = getRange(arr) or const { data, error } = useFetch(url).
Rest in destructuring collects remaining elements into a variable during assignment: const [a, ...b] = arr. Rest parameters collect extra function arguments: function f(first, ...rest) {}. Both use the ... syntax but in different contexts.
Not directly via the object destructuring syntax, since Map keys are not properties. However, you can use array destructuring with the iterator: const [[k1, v1], [k2, v2]] = map.
No. Destructuring is purely syntactic sugar; modern JavaScript engines optimise it to the same bytecode as manual property access. Do not avoid it for performance reasons.

