Back to Blog
JavaScriptES6DestructuringPatterns

JavaScript Destructuring Patterns

Master JavaScript destructuring. From arrays to objects to nested patterns and defaults.

B
Bootspring Team
Engineering
September 6, 2020
7 min read

Destructuring extracts values from arrays and objects cleanly. Here's how to use it effectively.

Array Destructuring#

1// Basic array destructuring 2const colors = ['red', 'green', 'blue']; 3const [first, second, third] = colors; 4// first = 'red', second = 'green', third = 'blue' 5 6// Skip elements 7const [primary, , tertiary] = colors; 8// primary = 'red', tertiary = 'blue' 9 10// Rest pattern 11const numbers = [1, 2, 3, 4, 5]; 12const [head, ...tail] = numbers; 13// head = 1, tail = [2, 3, 4, 5] 14 15// Default values 16const sparse = [1]; 17const [a, b = 10] = sparse; 18// a = 1, b = 10 19 20// Swapping variables 21let x = 1, y = 2; 22[x, y] = [y, x]; 23// x = 2, y = 1 24 25// From functions 26function getCoordinates() { 27 return [10, 20]; 28} 29const [coordX, coordY] = getCoordinates();

Object Destructuring#

1// Basic object destructuring 2const user = { name: 'Alice', age: 30, email: 'alice@example.com' }; 3const { name, age } = user; 4// name = 'Alice', age = 30 5 6// Renaming variables 7const { name: userName, age: userAge } = user; 8// userName = 'Alice', userAge = 30 9 10// Default values 11const config = { host: 'localhost' }; 12const { host, port = 3000 } = config; 13// host = 'localhost', port = 3000 14 15// Rename with default 16const { port: serverPort = 8080 } = config; 17// serverPort = 8080 18 19// Rest pattern 20const { name: n, ...rest } = user; 21// n = 'Alice', rest = { age: 30, email: 'alice@example.com' } 22 23// Computed property names 24const key = 'name'; 25const { [key]: value } = user; 26// value = 'Alice'

Nested Destructuring#

1// Nested objects 2const company = { 3 name: 'TechCorp', 4 address: { 5 city: 'San Francisco', 6 country: 'USA', 7 }, 8 employees: [ 9 { name: 'Alice', role: 'Engineer' }, 10 { name: 'Bob', role: 'Designer' }, 11 ], 12}; 13 14const { 15 name: companyName, 16 address: { city, country }, 17} = company; 18// companyName = 'TechCorp', city = 'San Francisco', country = 'USA' 19 20// Nested arrays 21const matrix = [[1, 2], [3, 4], [5, 6]]; 22const [[a, b], [c, d]] = matrix; 23// a = 1, b = 2, c = 3, d = 4 24 25// Mixed nesting 26const { 27 employees: [firstEmployee, secondEmployee], 28} = company; 29// firstEmployee = { name: 'Alice', role: 'Engineer' } 30 31// Deep extraction 32const { 33 employees: [{ name: firstName }], 34} = company; 35// firstName = 'Alice'

Function Parameters#

1// Object parameters 2function createUser({ name, age, email = 'default@email.com' }) { 3 return { name, age, email }; 4} 5 6createUser({ name: 'Alice', age: 30 }); 7 8// With defaults for entire parameter 9function greet({ name = 'Guest', greeting = 'Hello' } = {}) { 10 return `${greeting}, ${name}!`; 11} 12 13greet(); // 'Hello, Guest!' 14greet({ name: 'Alice' }); // 'Hello, Alice!' 15 16// Array parameters 17function sum([first, second, ...rest]) { 18 return first + second + rest.reduce((a, b) => a + b, 0); 19} 20 21sum([1, 2, 3, 4]); // 10 22 23// React component props 24function UserCard({ name, avatar, role = 'User' }) { 25 return ( 26 <div> 27 <img src={avatar} alt={name} /> 28 <h2>{name}</h2> 29 <span>{role}</span> 30 </div> 31 ); 32}

Advanced Patterns#

1// Multiple return values 2function getMinMax(arr) { 3 return { 4 min: Math.min(...arr), 5 max: Math.max(...arr), 6 }; 7} 8 9const { min, max } = getMinMax([1, 5, 3, 9, 2]); 10 11// Optional chaining with destructuring 12const data = { user: null }; 13const { user: { name } = {} } = data; 14// name = undefined (no error) 15 16// Destructuring in loops 17const users = [ 18 { id: 1, name: 'Alice' }, 19 { id: 2, name: 'Bob' }, 20]; 21 22for (const { id, name } of users) { 23 console.log(`${id}: ${name}`); 24} 25 26// Map entries 27const map = new Map([ 28 ['a', 1], 29 ['b', 2], 30]); 31 32for (const [key, value] of map) { 33 console.log(`${key}: ${value}`); 34} 35 36// Regex groups 37const regex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/; 38const match = regex.exec('2024-01-15'); 39const { groups: { year, month, day } } = match;

Practical Examples#

1// API response handling 2async function fetchUser(id) { 3 const response = await fetch(`/api/users/${id}`); 4 const { data: user, meta: { timestamp } } = await response.json(); 5 return { user, timestamp }; 6} 7 8// Event handling 9document.addEventListener('click', ({ target, clientX, clientY }) => { 10 console.log(`Clicked ${target.tagName} at (${clientX}, ${clientY})`); 11}); 12 13// Module imports 14import { useState, useEffect, useCallback } from 'react'; 15 16// Configuration objects 17function initApp({ 18 port = 3000, 19 host = 'localhost', 20 debug = false, 21 database: { 22 url = 'mongodb://localhost', 23 name = 'mydb', 24 } = {}, 25} = {}) { 26 console.log(`Starting on ${host}:${port}`); 27 console.log(`Database: ${url}/${name}`); 28 console.log(`Debug: ${debug}`); 29} 30 31initApp({ 32 port: 8080, 33 database: { name: 'production' }, 34}); 35 36// React hooks 37function useForm(initialValues) { 38 const [values, setValues] = useState(initialValues); 39 40 const handleChange = ({ target: { name, value } }) => { 41 setValues(prev => ({ ...prev, [name]: value })); 42 }; 43 44 return { values, handleChange }; 45}

Combining with Spread#

1// Clone and modify 2const original = { a: 1, b: 2, c: 3 }; 3const { a, ...withoutA } = original; 4const modified = { ...withoutA, d: 4 }; 5// { b: 2, c: 3, d: 4 } 6 7// Merge with override 8const defaults = { theme: 'light', lang: 'en' }; 9const userPrefs = { theme: 'dark' }; 10const { theme, lang } = { ...defaults, ...userPrefs }; 11// theme = 'dark', lang = 'en' 12 13// Pick properties 14function pick(obj, keys) { 15 return keys.reduce((acc, key) => { 16 if (key in obj) acc[key] = obj[key]; 17 return acc; 18 }, {}); 19} 20 21// Omit properties 22function omit(obj, keys) { 23 const keysSet = new Set(keys); 24 return Object.fromEntries( 25 Object.entries(obj).filter(([key]) => !keysSet.has(key)) 26 ); 27} 28 29// Usage 30const user = { id: 1, name: 'Alice', password: 'secret' }; 31const safeUser = omit(user, ['password']); 32// { id: 1, name: 'Alice' }

Error Handling#

1// Safe destructuring with defaults 2function processData(data) { 3 const { 4 items = [], 5 meta: { page = 1, total = 0 } = {}, 6 } = data || {}; 7 8 return { items, page, total }; 9} 10 11// Handles: null, undefined, missing properties 12processData(null); // { items: [], page: 1, total: 0 } 13processData({}); // { items: [], page: 1, total: 0 } 14processData({ items: [1, 2] }); // { items: [1, 2], page: 1, total: 0 } 15 16// Try-catch for complex cases 17function safeDestructure(obj, path, defaultValue) { 18 try { 19 const keys = path.split('.'); 20 let result = obj; 21 for (const key of keys) { 22 result = result[key]; 23 } 24 return result ?? defaultValue; 25 } catch { 26 return defaultValue; 27 } 28}

TypeScript Destructuring#

1// Typed destructuring 2interface User { 3 name: string; 4 age: number; 5 email?: string; 6} 7 8function greet({ name, age }: User): string { 9 return `Hello ${name}, you are ${age}`; 10} 11 12// With defaults 13function createUser({ 14 name, 15 age, 16 email = 'default@email.com', 17}: Partial<User> & { name: string }) { 18 return { name, age, email }; 19} 20 21// Array types 22function processCoords([x, y]: [number, number]): number { 23 return x + y; 24} 25 26// Rest with types 27function logAll({ name, ...rest }: User & Record<string, unknown>) { 28 console.log(name, rest); 29}

Best Practices#

Readability: ✓ Keep destructuring shallow when possible ✓ Use meaningful variable names ✓ Add defaults for optional values ✓ Break complex patterns into steps Safety: ✓ Provide defaults for nested objects ✓ Use || {} for potentially undefined ✓ Consider optional chaining ✓ Validate before destructuring Performance: ✓ Destructure only what you need ✓ Avoid repeated destructuring ✓ Use rest sparingly in hot paths ✓ Profile complex patterns Avoid: ✗ Deeply nested destructuring ✗ Destructuring in loops (sometimes) ✗ Confusing rename chains ✗ Missing defaults for optional props

Conclusion#

Destructuring makes code cleaner and more expressive. Use array destructuring for ordered data, object destructuring for named properties, and combine with defaults for safety. Keep patterns simple and readable, especially with nested structures.

Share this article

Help spread the word about Bootspring