Skip to main content

Destructuring assignment in JavaScript

Destructuring assignment is a JavaScript syntax that pulls values from arrays or properties from objects into individual variables, in one step instead of multiple manual assignments.

Theory

TL;DR

  • Think of it like unpacking a labeled box: you name each slot and pull only what you need
  • Arrays match by position; objects match by key name
  • Defaults apply only when the value is undefined, not when it is null or 0
  • Rest (...) collects remaining items and must always come last
  • Use it when extracting 2+ values; for a single value, dot notation is cleaner

Quick example

javascript
// Array: position-based const [first, second] = [10, 20, 30]; console.log(first); // 10 console.log(second); // 20 // Object: key-based const user = { name: 'Alice', age: 25 }; const { name, age } = user; console.log(name); // 'Alice' console.log(age); // 25

The engine reads left-to-right: for arrays it uses indices, for objects it looks up the property name. The compiled output is equivalent to manual assignment, so there is no performance difference.

When to use

  • API responses with multiple fields: const { data, error } = await fetchUser(id)
  • Function parameters from an object: function greet({ name, role = 'user' }) {}
  • Variable swapping: [a, b] = [b, a] without a temp variable
  • React hooks: const [count, setCount] = useState(0)
  • Named imports: import { useState, useEffect } from 'react'

Skip it for a single value. user.name is more readable than const { name } = user when that is all you need.

Array patterns

Skipping elements uses an empty slot:

javascript
const [first, , third] = [1, 2, 3]; console.log(third); // 3

Rest gathers the remaining items:

javascript
const [head, ...tail] = [1, 2, 3, 4]; console.log(tail); // [2, 3, 4]

Defaults fill in only when the value is undefined:

javascript
const [x = 5] = [0]; console.log(x); // 0 (not 5, because 0 is not undefined)

Object patterns

Rename a property with a colon after the key:

javascript
const { name: userName } = { name: 'Alice' }; console.log(userName); // 'Alice'

Nested patterns require nested syntax:

javascript
const { address: { city } } = { address: { city: 'Kyiv' } }; console.log(city); // 'Kyiv'

If address is undefined, this throws a TypeError. Add a default or use optional chaining before destructuring.

Rest on objects collects all remaining keys:

javascript
const { id, ...rest } = { id: 1, name: 'Alice', age: 25 }; console.log(rest); // { name: 'Alice', age: 25 }

Common mistakes

Nested destructuring throws on undefined.

javascript
const data = {}; const { user: { name } } = data; // TypeError: Cannot read properties of undefined

Fix: const { user: { name } = {} } = data or use data.user?.name.

Rest cannot come before the last position.

javascript
const [...rest, last] = [1, 2, 3]; // SyntaxError

Rest must be the final element. [first, ...rest] works. [...rest, last] does not compile.

Wrong key name when renaming.

javascript
const { userName } = { name: 'Alice' }; console.log(userName); // undefined

userName looks for a key literally called userName. Use { name: userName } to rename it.

Defaults do not replace null.

javascript
const [x = 5] = [null]; console.log(x); // null (defaults only apply for undefined)

Real-world usage

  • React: const [value, setValue] = useState(''), component props function Button({ onClick, label })
  • Express/Node.js: const { id } = req.params, const { page = 1 } = req.query
  • Redux Toolkit: const { type, payload: { id } } = action
  • SWR/React Query: const { data, error } = useSWR('/api/user')

Follow-up questions

Q: What does const [x = 1] = [0] output?
A: 0. The default only applies when the value is undefined. Zero is a valid defined value.

Q: What happens when you destructure a key that does not exist on the object?
A: You get undefined. No error is thrown unless you then try to destructure a property of that undefined value.

Q: How do null and undefined behave differently with defaults?
A: Only undefined triggers the default. null passes through as-is. This catches many people off guard during interviews.

Q: Can you destructure a function return value inline?
A: Yes. const [success, data] = await fetchData() works whenever the function returns an array.

Q: (Senior) How does V8 compile const { x } = obj?
A: It emits a GetOwnProperty check for key x on obj, then assigns the result to a new binding. Array patterns compile to indexed accesses like arr[0]. Rest uses property enumeration or slice. The bytecode is equivalent to manual assignment, so there is no runtime overhead.

Examples

Basic: arrays and objects

javascript
const coords = [10, 20, 30]; const [x, y] = coords; console.log(x, y); // 10 20 const product = { title: 'Keyboard', price: 99, stock: 5 }; const { title, price } = product; console.log(title, price); // 'Keyboard' 99

Array destructuring picks by index, object destructuring picks by key. A missing key gives undefined, not an error.

Real-world: function params with defaults

javascript
// The expected shape of input is visible right at the signature function handleRequest({ params: { id }, query: { role = 'viewer', page = 1 } }) { console.log(id, role, page); } handleRequest({ params: { id: '42' }, query: { role: 'admin' } }); // '42', 'admin', 1

This pattern appears in React components, Express handlers, and Redux reducers. I find it most useful here: you see what the function expects without reading the body. That alone cuts the time spent understanding unfamiliar code.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.

Finished reading?