Destructuring and Spread Operator
Modern JavaScript techniques for working with objects and arrays
Challenge
Section titled “Challenge”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?
Explanation
Section titled “Explanation”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.
Array Destructuring
Section titled “Array Destructuring”// Basic destructuringconst [first, second, third] = [1, 2, 3];console.log(first, second, third); // 1, 2, 3
// Skip elementsconst [head, , , tail] = [1, 2, 3, 4];console.log(head, tail); // 1, 4
// Default valuesconst [x = 10, y = 20] = [5];console.log(x, y); // 5, 20
// Rest elementsconst [first, ...rest] = [1, 2, 3, 4, 5];console.log(first); // 1console.log(rest); // [2, 3, 4, 5]
// Swap variableslet a = 1, b = 2;[a, b] = [b, a];console.log(a, b); // 2, 1Object Destructuring
Section titled “Object Destructuring”const user = { name: 'Alice', email: 'alice@example.com', profile: { age: 30, city: 'NYC' }};
// Basic destructuringconst { name, email } = user;console.log(name, email); // Alice, alice@example.com
// Rename variablesconst { name: userName, email: userEmail } = user;
// Nested destructuringconst { profile: { age, city } } = user;console.log(age, city); // 30, NYC
// Default valuesconst { name, country = 'USA' } = user;console.log(country); // USA
// Rest propertiesconst { name, ...rest } = user;console.log(rest); // { email, profile: {...} }Solution: Extracting API Data
Section titled “Solution: Extracting API Data”// Complex API responseconst 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 defaultsconst { data: { user: { name = 'Guest', email = 'no-email@example.com', address: { city = 'Unknown' } = {} } = {} } = {}} = apiResponse;
console.log(name, email, city); // John, john@example.com, BostonSpread Operator
Section titled “Spread Operator”// Array spreadconst arr1 = [1, 2, 3];const arr2 = [4, 5, 6];const merged = [...arr1, ...arr2];console.log(merged); // [1, 2, 3, 4, 5, 6]
// Object spreadconst 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 copyconst original = { x: 1, nested: { y: 2 } };const copy = { ...original };copy.nested.y = 99; // Affects original too!console.log(original.nested.y); // 99
// Override propertiesconst defaults = { theme: 'light', language: 'en' };const userPrefs = { theme: 'dark' };const settings = { ...defaults, ...userPrefs };console.log(settings); // { theme: 'dark', language: 'en' }Rest Parameters
Section titled “Rest Parameters”// Collect remaining argumentsfunction 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 argumentsfunction logMessages(level, ...messages) { console.log(`[${level}]`, messages.join(' '));}
logMessages('INFO', 'User', 'logged', 'in');// [INFO] User logged inCombining Patterns
Section titled “Combining Patterns”// Complex destructuring with defaultsfunction 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 objectsconst createComponent = ({ name = 'Component', props = {}, children = [], ...rest}) => { return { name, props: { ...props, ...rest }, children };};
const component = createComponent({ name: 'Button', onClick: () => {}, className: 'primary', children: ['Click me']});Performance Note: Deep Copy
Section titled “Performance Note: Deep Copy”// ⚠️ Spread only does shallow copyconst 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));