Learning Objectives
- Extract values from arrays with array destructuring
- Extract properties from objects with object destructuring
- Use destructuring in function parameters
- Apply default values and renaming
- Handle nested destructuring patterns
What is Destructuring?
Destructuring is a JavaScript expression that unpacks values from arrays or properties from objects into distinct variables. It provides a cleaner, more readable way to extract data.
Array Destructuring
Basic Array Destructuring
// Without destructuring
const colors = ['red', 'green', 'blue'];
const first = colors[0];
const second = colors[1];
// With destructuring
const [first, second, third] = colors;
console.log(first); // 'red'
console.log(second); // 'green'
console.log(third); // 'blue'
Skipping Elements
const colors = ['red', 'green', 'blue', 'yellow'];
// Skip elements with commas
const [first, , third] = colors;
console.log(first); // 'red'
console.log(third); // 'blue'
// Get first and rest
const [primary, ...others] = colors;
console.log(primary); // 'red'
console.log(others); // ['green', 'blue', 'yellow']
Default Values
const colors = ['red'];
// Without default
const [first, second] = colors;
console.log(second); // undefined
// With default
const [first, second = 'green'] = colors;
console.log(second); // 'green'
Swapping Variables
let a = 1;
let b = 2;
// Old way
let temp = a;
a = b;
b = temp;
// With destructuring
[a, b] = [b, a];
console.log(a); // 2
console.log(b); // 1
Object Destructuring
Basic Object Destructuring
const user = {
name: 'John',
age: 30,
email: 'john@example.com'
};
// Without destructuring
const name = user.name;
const age = user.age;
// With destructuring
const { name, age, email } = user;
console.log(name); // 'John'
console.log(age); // 30
console.log(email); // 'john@example.com'
Renaming Variables
const user = {
name: 'John',
age: 30
};
// Rename during destructuring
const { name: userName, age: userAge } = user;
console.log(userName); // 'John'
console.log(userAge); // 30
Default Values
const user = {
name: 'John'
};
// With default values
const { name, age = 25, country = 'USA' } = user;
console.log(name); // 'John'
console.log(age); // 25 (default)
console.log(country); // 'USA' (default)
Combining Rename and Default
const user = {
name: 'John'
};
const { name: userName, age: userAge = 25 } = user;
console.log(userName); // 'John'
console.log(userAge); // 25
Nested Destructuring
Nested Objects
const user = {
name: 'John',
address: {
street: '123 Main St',
city: 'New York',
coordinates: {
lat: 40.7128,
lng: -74.0060
}
}
};
// Destructure nested properties
const {
name,
address: {
city,
coordinates: { lat, lng }
}
} = user;
console.log(name); // 'John'
console.log(city); // 'New York'
console.log(lat); // 40.7128
console.log(lng); // -74.0060
// Note: 'address' and 'coordinates' are not variables
// console.log(address); // ReferenceError
Nested Arrays
const data = [
'John',
['red', 'green', 'blue'],
{ age: 30 }
];
const [name, [primaryColor, ...otherColors], { age }] = data;
console.log(name); // 'John'
console.log(primaryColor); // 'red'
console.log(otherColors); // ['green', 'blue']
console.log(age); // 30
Function Parameter Destructuring
Object Parameters
// Without destructuring
function displayUser(user) {
console.log(`${user.name} is ${user.age} years old`);
}
// With destructuring
function displayUser({ name, age }) {
console.log(`${name} is ${age} years old`);
}
displayUser({ name: 'John', age: 30 });
// "John is 30 years old"
Default Parameter Values
function createUser({ name, age = 18, role = 'user' }) {
return { name, age, role };
}
console.log(createUser({ name: 'John' }));
// { name: 'John', age: 18, role: 'user' }
console.log(createUser({ name: 'Jane', age: 25, role: 'admin' }));
// { name: 'Jane', age: 25, role: 'admin' }
Handling Undefined Parameters
// This will error if called without argument
function greet({ name }) {
console.log(`Hello, ${name}!`);
}
// greet(); // TypeError: Cannot destructure property 'name' of 'undefined'
// Solution: default to empty object
function greet({ name } = {}) {
console.log(`Hello, ${name || 'Guest'}!`);
}
greet(); // "Hello, Guest!"
Rest Operator with Destructuring
Array Rest
const numbers = [1, 2, 3, 4, 5];
const [first, second, ...rest] = numbers;
console.log(first); // 1
console.log(second); // 2
console.log(rest); // [3, 4, 5]
Object Rest
const user = {
name: 'John',
age: 30,
email: 'john@example.com',
country: 'USA'
};
const { name, age, ...otherInfo } = user;
console.log(name); // 'John'
console.log(age); // 30
console.log(otherInfo); // { email: 'john@example.com', country: 'USA' }
Real-World Examples
API Response Handling
async function fetchUser(id) {
const response = await fetch(`/api/users/${id}`);
const { data: user, status, message } = await response.json();
if (status === 'success') {
const { name, email, profile: { avatar } } = user;
return { name, email, avatar };
}
throw new Error(message);
}
React Component Props
// Destructure props in function component
function UserCard({ name, age, email, avatar = '/default-avatar.png' }) {
return (
<div className="user-card">
<img src={avatar} alt={name} />
<h2>{name}</h2>
<p>Age: {age}</p>
<p>Email: {email}</p>
</div>
);
}
Array Methods
const users = [
{ id: 1, name: 'John', age: 30 },
{ id: 2, name: 'Jane', age: 25 },
{ id: 3, name: 'Bob', age: 35 }
];
// Destructure in map
const names = users.map(({ name }) => name);
console.log(names); // ['John', 'Jane', 'Bob']
// Destructure in filter
const adults = users.filter(({ age }) => age >= 30);
console.log(adults); // [{ id: 1, ... }, { id: 3, ... }]
// Destructure in forEach
users.forEach(({ name, age }) => {
console.log(`${name} is ${age} years old`);
});
Configuration Objects
function initializeApp({
apiUrl = 'https://api.example.com',
timeout = 5000,
retries = 3,
headers = {},
debug = false
} = {}) {
console.log('Initializing with config:');
console.log({ apiUrl, timeout, retries, headers, debug });
// Initialize app with config
}
// Use with custom config
initializeApp({
apiUrl: 'https://custom-api.com',
debug: true
});
// Use with defaults
initializeApp();
Common Pitfalls
Pitfall 1: Destructuring undefined/null
const user = null;
// const { name } = user; // TypeError!
// Solution: use optional chaining or default
const { name } = user || {};
const { name } = user ?? {};
Pitfall 2: Variable already declared
let name = 'Alice';
// let { name } = user; // SyntaxError: Identifier 'name' has already been declared
// Solution: use different name or reassign
let { name: userName } = user;
// or
({ name } = user); // Note the parentheses!
Pitfall 3: Rest must be last
// Wrong
// const [...rest, last] = array; // SyntaxError
// Right
const [first, ...rest] = array;
Best Practices
1. Use destructuring for cleaner code
// Instead of
function getFullName(user) {
return user.firstName + ' ' + user.lastName;
}
// Use
function getFullName({ firstName, lastName }) {
return `${firstName} ${lastName}`;
}
2. Provide defaults for optional properties
function createConfig({ port = 3000, host = 'localhost' } = {}) {
return { port, host };
}
3. Use meaningful variable names when renaming
// Good
const { name: userName, id: userId } = user;
// Avoid
const { name: n, id: i } = user;
Key Takeaways
- Destructuring extracts values from arrays and objects into variables
- Array destructuring uses square brackets
[] - Object destructuring uses curly braces
{} - You can provide default values for missing properties
- Rename variables during destructuring with
: - Rest operator
...collects remaining elements - Destructuring works in function parameters for cleaner APIs
- Nested destructuring extracts deeply nested values
- Always handle undefined/null cases to avoid errors