Start.dev
Back to blog

JavaScript destructuring explained with simple examples

Destructuring unpacks objects and arrays into variables in one line. Learn renaming, defaults, nested values, function arguments and the undefined error.

Ariel Weinberger
Ariel Weinberger ยท 5 min read

What does const { name, age } = user actually do, and why does it show up in every React component and API example?

Short answer: destructuring unpacks values from an object or an array into separate variables in one line. Curly braces {} pull values out of an object by property name, and square brackets [] pull values out of an array by position.

By the end of this post you will destructure objects and arrays, rename values and give them defaults, reach into nested data, destructure function arguments, and fix the error that trips most people up. If objects and arrays are still new, start with What Is An Object (opens in a new tab) and What Is An Array (opens in a new tab).

Object destructuring: pick values by name

Without destructuring, you read each property one at a time:

const user = { name: "Ana", age: 30, address: { city: "Lisbon" } };
 
const name = user.name;
const age = user.age;

With destructuring, it's one line:

const { name, age } = user;
console.log(name, age); // Ana 30

The names inside {} must match property names on the object. Order doesn't matter, and you only take what you need. Asking for a property that isn't there gives undefined, not an error.

Rename and set defaults

Use a colon to store a value under a different name, and = to give it a fallback:

const { name: userName, role = "student" } = user;
console.log(userName); // Ana
console.log(role);     // student, because user has no role

Read name: userName as "take name and call it userName". You can combine both: { role: userRole = "student" }.

One detail that surprises people: a default only kicks in when the value is undefined. If the property exists and is null, you get null:

const { theme = "light" } = { theme: null };
console.log(theme); // null

Reach into nested objects

Put another pair of braces where the nested object is:

const { address: { city } } = user;
console.log(city); // Lisbon

This creates a city variable, but not an address one. Keep nesting shallow, though. Two levels is usually where it stops being easier to read than user.address.city.

Array destructuring: pick values by position

Square brackets unpack an array in order:

const scores = [95, 82, 77];
const [first, second] = scores;
console.log(first, second); // 95 82

Skip a position with an empty slot, and give defaults the same way as with objects:

const [winner, , third = "none"] = ["Bo", "Ana"];
console.log(winner, third); // Bo none

It also gives you a neat way to swap two variables without a temporary one:

let a = 1;
let b = 2;
[a, b] = [b, a];
console.log(a, b); // 2 1

You've probably seen array destructuring already in React: const [count, setCount] = useState(0) takes the two values useState returns. Our post on useState vs useReducer uses it throughout.

Collect the rest with ...

... gathers whatever you didn't name:

const { name, ...details } = user;
console.log(details); // { age: 30, address: { city: "Lisbon" } }
 
const [top, ...others] = [95, 82, 77];
console.log(others); // [82, 77]

The rest element has to come last. It's a handy way to remove one property, but note that it's a shallow copy: details.address is still the same object as user.address. Our post on value vs reference explains why that matters.

Destructuring (opens in a new tab) and Spread And Rest (opens in a new tab) practice all of this.

Destructuring function arguments

This is where destructuring earns its keep, and where most people get stuck. Instead of accepting an object and reading properties inside, destructure right in the parameter list:

function greet({ name, greeting = "Hi" }) {
  return `${greeting}, ${name}`;
}
 
greet({ name: "Bo" });                    // "Hi, Bo"
greet({ name: "Ana", greeting: "Hey" });  // "Hey, Ana"

The function's signature now shows exactly which properties it uses, callers can pass them in any order, and optional ones get defaults. Destructuring In Functions (opens in a new tab) practices this.

There's one catch. Call it with nothing and it throws:

greet();
// TypeError: Cannot destructure property 'name' of 'undefined' as it is undefined.

You can't destructure undefined. The fix is a default for the whole parameter, = {}:

function greet({ name, greeting = "Hi" } = {}) {
  return `${greeting}, ${name}`;
}
 
greet(); // "Hi, undefined"

Now an empty call destructures an empty object instead of crashing. You'll see the same error when an API response is missing a field you destructure from, so it's worth recognizing.

Destructuring in loops

Destructuring works anywhere you declare variables, including loops:

const prices = { popcorn: 4.5, soda: 2.25 };
 
for (const [item, price] of Object.entries(prices)) {
  console.log(`${item}: ${price}`);
}

Object.entries() gives you [key, value] pairs, and the brackets unpack each one. Array methods like map and filter take destructured parameters too: users.map(({ name }) => name).

Common mistakes

  • Destructuring undefined or null. Cannot destructure property 'x' of 'undefined' means the thing on the right didn't exist. Add a default, like = {} on a parameter, or check before you destructure.
  • Expecting a default to replace null. Defaults only apply to undefined. Use value ?? fallback if null should also fall back.
  • Assigning to existing variables without parentheses. { total } = order; is a syntax error, because a line starting with { looks like a block. Wrap it: ({ total } = order);.
  • Mixing up braces and brackets. {} matches by name and works on objects. [] matches by position and works on arrays and other iterables.
  • Nesting too deeply. If a destructuring line is hard to read, pull out one level at a time.

Quick recap

  • const { a, b } = obj takes properties by name.
  • const [x, y] = arr takes items by position.
  • name: newName renames, and = value sets a default for undefined.
  • ...rest collects everything you didn't name, as a shallow copy.
  • In function parameters, add = {} so a call with no arguments doesn't crash.

Frequently asked questions

What is destructuring in JavaScript?

It's syntax for unpacking values from objects or arrays into variables. const { name } = user is the same as const name = user.name, and it scales nicely when you need several values at once.

What's the difference between object and array destructuring?

Object destructuring uses {} and matches values by property name. Array destructuring uses [] and matches values by position.

Why do I get "Cannot destructure property of undefined"?

The value on the right side is undefined, often because a function was called without an argument or an API response is missing a field. Add a default, such as = {} on the parameter, or check the value first.

Can I destructure and rename at the same time?

Yes. const { name: userName } = user reads user.name into a variable called userName.

Practice

Try it in your browser, with nothing to install: Destructuring (opens in a new tab) for the basics, then Destructuring (opens in a new tab), Destructuring In Functions (opens in a new tab) and Spread And Rest (opens in a new tab). For more reps, try the JavaScript Objects and JavaScript Arrays challenges.

Where to go next

Destructuring sits in the modern JavaScript module of Intermediate JavaScript (opens in a new tab), right before the course's watchlist project. It pairs naturally with JavaScript array methods, since you'll often destructure inside map() and filter().

Level up your coding skills

Jump into interactive courses and start building real-world projects.

Start learning

Related posts

Learn the JavaScript array methods you will use daily: map, filter, find, some, every, reduce and sort, with runnable examples on one shopping cart.
Ariel Weinberger
Ariel Weinberger ยท 5 min read
useState or useReducer? See the same cart built both ways, the signs it's time to switch, and a simple rule of thumb for choosing in your React components.
Ariel Weinberger
Ariel Weinberger ยท 5 min read
You copied an array, changed the copy, and the original changed too. Here is what a JavaScript variable actually holds and how to copy safely.
Ariel Weinberger
Ariel Weinberger ยท 6 min read