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 |
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?
ποΈ 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.
Frequently Asked Questions
- Does destructuring mutate the original object or array?
- 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.
- Can I destructure a function's return value?
- 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)orconst { data, error } = useFetch(url). - What is the difference between rest in destructuring and rest parameters?
- 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. - Can I use destructuring with a Map?
- 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. - Is destructuring performance-intensive?
- 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.
π 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.