Skip to content
Plurafy

Destructuring and Spread Operator

Modern JavaScript techniques for working with objects and arrays

You have nested API response data and need to extract specific fields while providing defaults. How can you write clean code that handles missing properties?

Destructuring allows you to unpack values from objects and arrays into distinct variables. The spread operator enables shallow copying and merging. Together, they provide powerful patterns for data manipulation.

// Basic destructuring
const [first, second, third] = [1, 2, 3];
console.log(first, second, third); // 1, 2, 3
// Skip elements
const [head, , , tail] = [1, 2, 3, 4];
console.log(head, tail); // 1, 4
// Default values
const [x = 10, y = 20] = [5];
console.log(x, y); // 5, 20
// Rest elements
const [first, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(rest); // [2, 3, 4, 5]
// Swap variables
let a = 1, b = 2;
[a, b] = [b, a];
console.log(a, b); // 2, 1
const user = {
name: 'Alice',
email: 'alice@example.com',
profile: {
age: 30,
city: 'NYC'
}
};
// Basic destructuring
const { name, email } = user;
console.log(name, email); // Alice, alice@example.com
// Rename variables
const { name: userName, email: userEmail } = user;
// Nested destructuring
const { profile: { age, city } } = user;
console.log(age, city); // 30, NYC
// Default values
const { name, country = 'USA' } = user;
console.log(country); // USA
// Rest properties
const { name, ...rest } = user;
console.log(rest); // { email, profile: {...} }
// Complex API response
const apiResponse = {
data: {
user: {
id: 1,
name: 'John',
email: 'john@example.com',
address: {
street: '123 Main St',
city: 'Boston'
}
},
meta: {
timestamp: Date.now()
}
}
};
// ✅ Clean extraction with defaults
const {
data: {
user: {
name = 'Guest',
email = 'no-email@example.com',
address: {
city = 'Unknown'
} = {}
} = {}
} = {}
} = apiResponse;
console.log(name, email, city); // John, john@example.com, Boston
// Array spread
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const merged = [...arr1, ...arr2];
console.log(merged); // [1, 2, 3, 4, 5, 6]
// Object spread
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const merged = { ...obj1, ...obj2 };
console.log(merged); // { a: 1, b: 2, c: 3, d: 4 }
// Shallow copy
const original = { x: 1, nested: { y: 2 } };
const copy = { ...original };
copy.nested.y = 99; // Affects original too!
console.log(original.nested.y); // 99
// Override properties
const defaults = { theme: 'light', language: 'en' };
const userPrefs = { theme: 'dark' };
const settings = { ...defaults, ...userPrefs };
console.log(settings); // { theme: 'dark', language: 'en' }
// Collect remaining arguments
function sum(first, second, ...rest) {
console.log(first, second); // 1, 2
console.log(rest); // [3, 4, 5]
return first + second + rest.reduce((a, b) => a + b, 0);
}
console.log(sum(1, 2, 3, 4, 5)); // 15
// Function with flexible arguments
function logMessages(level, ...messages) {
console.log(`[${level}]`, messages.join(' '));
}
logMessages('INFO', 'User', 'logged', 'in');
// [INFO] User logged in
// Complex destructuring with defaults
function fetchUserData({
id,
userId = id,
includePosts = false,
includeComments = false,
limit = 10
} = {}) {
console.log(`Fetching user ${userId} with options:`, {
posts: includePosts,
comments: includeComments,
limit
});
}
fetchUserData({
id: 5,
includeComments: true
});
// Practical example: Configuration objects
const createComponent = ({
name = 'Component',
props = {},
children = [],
...rest
}) => {
return {
name,
props: { ...props, ...rest },
children
};
};
const component = createComponent({
name: 'Button',
onClick: () => {},
className: 'primary',
children: ['Click me']
});
// ⚠️ Spread only does shallow copy
const original = {
user: { name: 'Alice' },
settings: { theme: 'dark' }
};
const shallow = { ...original };
shallow.user.name = 'Bob';
console.log(original.user.name); // 'Bob' - affected!
// ✅ For deep copy, use structured clone (modern)
const deep = structuredClone(original);
deep.user.name = 'Charlie';
console.log(original.user.name); // 'Alice' - unaffected
// ✅ Or JSON (if no functions/circular refs)
const deepAlt = JSON.parse(JSON.stringify(original));