completefrontend
Open lab My progress
THE JAVASCRIPT FIELD GUIDE

Destructuring

Learn how JavaScript destructuring unpacks arrays and objects into variables, with defaults, renaming, nested patterns, parameters, swaps, and the evaluation rules that prevent surprises.

By the end you can
  • 01
    Unpack arrays and objectsTake values out of an array by position, and out of an object by property name.
  • 02
    Use patterns safelyUse defaults, renaming, patterns inside patterns, and parameter defaults without errors.
  • 03
    Predict tricky casesSay when a default is used, why null keeps its value, and why unpacking into existing variables needs round brackets.

Unpack many values in one line

Destructuring is a short way to take values out of an array or an object and put them into variables. Without it, you write one line for each value you want. With it, you write one pattern. A pattern is a small sketch of the data, with a variable name in each spot you want filled.

The main idea

Put a pattern on the left of =. Put an array or an object on the right. JavaScript reads the right side and puts each value into the variable at the matching spot in the pattern.

Take two values out of an arrayPop out in the code editor (opens in a new tab)JavaScript
const order = ["tea", 3];
const [drink, quantity] = order;
console.log(drink, quantity);

Line 1 makes an array with two values: "tea" and 3. Line 2 has the pattern [drink, quantity]. It has the same shape as the array: two spots in a row. So drink gets the first value, "tea", and quantity gets the second value, 3. Line 3 prints tea 3.

Unpacking the array ["tea", 3]. The first value, tea, goes into a box called drink. The second value, 3, goes into a box called quantity.first"tea"second3"tea"drink3quantity
The pattern [drink, quantity] has two spots, like the array. The first value goes into the first variable. The second value goes into the second variable.
Real-life analogyA delivery box and labeled drawers

A delivery box arrives at your desk. Inside are a mug and a notebook. You put the mug in the drawer labeled mug. You put the notebook in the drawer labeled notes. The pattern is your list of drawer labels. It says where each item goes.

In real life: The items in the box
In JavaScript: The values in the array or object
In real life: The labels on your drawers
In JavaScript: The variable names in the pattern
In real life: A spare item, used only when one is missing
In JavaScript: A default value, like role = "guest"
In real life: Putting an item in a drawer with a different label
In JavaScript: Renaming, like { name: fullName }

This lesson starts with arrays and objects. Then it shows defaults, renaming, patterns inside patterns, function parameters, and swapping two variables. It ends with the exact rules for when a default is used.

Array destructuring

BY POSITION

An array pattern takes values by position. Position means the place in the row: first, second, third. The first name in the pattern gets the first value. The second name gets the second value, and so on.

Take values by position, or skip onePop out in the code editor (opens in a new tab)JavaScript
const scores = [98, 87, 91];
const [first, second] = scores;
const [winner, , bronze = 0] = scores;
console.log(first, second, bronze); // 98 87 91

Line 2 puts 98 in first and 87 in second. Line 3 shows two new things:

  • The empty spot between two commas skips a value. Here it skips 87, so no variable gets it.
  • bronze = 0 is a default value: a spare value for when nothing is there. The third value, 91, is there. So bronze gets 91, and the default is not used.
A default fills a missing itemPop out in the code editor (opens in a new tab)JavaScript
const cart = ["book"];
const [first, second = "pen"] = cart;
console.log(first, second);

This cart has only one item. Line 2 puts "book" in first. There is no second item, so the value for that spot is undefined. A default is used only when the value is undefined. So second gets the default, "pen", and line 3 prints book pen.

You may also see [head, ...tail]. The three dots make a rest pattern: tail gets all the values that are left, in a new array. The next lesson, Spread & rest, covers it fully.

Real-life analogySeats in a row

Three friends sit in a row. You can say "the person in seat 1" and "the person in seat 3" without knowing their names. You pick people by their seat number, not by their name.

In real life: Seat 1, seat 2, seat 3
In JavaScript: Array positions 0, 1, 2 (JavaScript counts from 0)
In real life: Skip the person in seat 2
In JavaScript: An empty spot: [first, , third]
In real life: Everyone after seat 1, as one group
In JavaScript: A rest pattern: [head, ...tail]
Unpack the letters of a stringPop out in the code editor (opens in a new tab)JavaScript
const word = "OK";
const [first, second] = word;
console.log(first, second);

A string can hand out its letters one at a time. So the same kind of pattern works on it. first gets "O", second gets "K", and line 3 prints O K.

A value that can hand out its items one by one, in order, is called an iterable. Arrays and strings are both iterables. An array pattern works with any iterable. The later lesson Iteration protocols explains how.

Object destructuring

BY NAME

An object pattern takes values by property name. A property is a named value inside an object, like name: "Mina". The pattern lists the names you want, and JavaScript finds each one in the object. The order of the properties in the object does not matter. It is like picking your own letters out of a row of mailboxes, where each mailbox has a person's name on it.

Take properties by namePop out in the code editor (opens in a new tab)JavaScript
const user = { id: 7, name: "Mina", role: "admin" };
const { name, role } = user;
console.log(name, role); // Mina admin

Line 2 asks for name and role. It creates two variables with those same names. id is not in the pattern, so it is left alone. Line 3 prints Mina admin.

Property order does not matterPop out in the code editor (opens in a new tab)JavaScript
const user = { role: "reader", name: "Asha" };
const { name, role } = user;
console.log(name, role);

Here the object lists role first and name second. The pattern lists them the other way round. It still works, because JavaScript looks up each one by its name. Line 3 prints Asha reader.

Sometimes you want the variable to have a different name from the property. Write the property name, a colon, and then the new variable name: { name: fullName }. Read it as "take the property name and put it in a new variable called fullName." Here the colon does not mean a type. It only means "put this property into that variable".

Defaults and renaming

INTERACTIVE

A default is a spare value: if the value is missing, the variable gets the spare. Renaming gives the variable a different name from the property. You can use both in one pattern.

Rename and default togetherPop out in the code editor (opens in a new tab)JavaScript
const profile = { name: "Asha" };
const { name: displayName, role = "reader" } = profile;
console.log(displayName, role);

Line 1 makes a profile object with only a name. Line 2 does two things:

  • name: displayName takes the name property and puts its value in a new variable, displayName.
  • role = "reader" asks for role. The object has no role, so the variable role gets the default, "reader".

Line 3 prints Asha reader.

Renaming. The profile cart holds a card that says name: "Asha". An arrow labeled name: displayName carries the value into a new box called displayName, which now holds "Asha".name: "Asha"profilereads namename: displayName"Asha"displayNamenew variable
name: displayName reads the property name and puts its value in a new variable, displayName. The object still calls it name.

Try both ideas in the lab below. Each button shows a different pattern on the same data. The right side lists the variables that pattern creates.

Unpacking lab
The data and your patternPop out in the code editor (opens in a new tab)JavaScript
const user = {  name: "Ada Lovelace",  age: 36,  address: { city: "Pune" }};const scores = [98, 87, 91, 76]; // Choose one pattern in the lab controls. const { name, age } = user;
Variables made2 made
name"Ada Lovelace"
age36
Try it yourself
Pattern:

The pattern asks for the properties name and age. JavaScript finds each one by its name. Where it sits in the object does not matter.

Pick a pattern. The right side lists the variables it makes from the same user object and scores array.

The table lists the patterns you will write most often. Read each row as: "when I write this pattern, this is what I get."

Common destructuring patterns and what they do
When you writeWhat you get
const [first, second] = list;Takes the first two items, by position.
const [first, , third] = list;The empty spot skips the second item.
const { name } = user;Takes the name property into a variable called name.
const { name: fullName } = user;Takes the name property into a new variable called fullName.
const { role = 'guest' } = user;Takes role, or 'guest' when the value is undefined.
const { address: { city } } = user;Goes into address and takes city. No address variable is made.

Nested patterns

SHAPES

A pattern can sit inside another pattern. This is called a nested pattern. It lets you reach into an object that is inside another object, or an array that is inside an object. Data from a server often has this shape.

Reach into an object inside an objectPop out in the code editor (opens in a new tab)JavaScript
const user = { address: { city: "Pune" } };
const { address: { city } } = user;
console.log(city);
console.log(address);

Line 1 makes user. Its address property holds another object, with a city inside. Line 2 reads like this: "go into address, then take city." Line 3 prints Pune.

Line 2 creates only one variable: city. The address: part is a path. It tells JavaScript where to go, but it does not create a variable called address. So line 4 throws a ReferenceError. That is the error JavaScript gives when you use a variable name that does not exist.

The pattern { address: { city } }. A tag that says address points into the address object, which holds city: "Pune". An arrow takes "Pune" into a box called city. The address tag is not a variable.const { address: { city } } = user;address:not a variablecity: "Pune"address"Pune"citynew variable
address: only shows the way in, like a sign. The one variable the pattern makes is city, which holds "Pune".
An array inside an objectPop out in the code editor (opens in a new tab)JavaScript
const response = { data: [{ id: 1, title: "Destructuring" }] };
const { data: [firstArticle] } = response;
const { id, title } = firstArticle;

This example mixes the two kinds of pattern. data holds an array. On line 2, the pattern { data: [firstArticle] } goes into data and takes its first item. Line 3 then unpacks that item in a second, separate step.

Take two properties from a nested objectPop out in the code editor (opens in a new tab)JavaScript
const response = { user: { name: "Asha", city: "Delhi" } };
const { user: { name, city } } = response;
console.log(name, city);

Here the pattern goes into response.user and takes two properties at once. Line 3 prints Asha Delhi. Destructuring only reads values. It does not make a copy of the user object.

Patterns in function parameters

OPTIONS

A function's parameters can be patterns too. A parameter is a name in the round brackets of a function, like name in function greet(name). Patterns here are common for an options object: the caller passes one object full of settings, and the function picks out the settings it needs. React components use the same idea for their props.

A parameter pattern that works with no argumentPop out in the code editor (opens in a new tab)JavaScript
function greet({ name, greeting = "Hello" } = {}) {
  return `${greeting}, ${name ?? "friend"}`;
}
console.log(greet({ name: "Mina" }));
console.log(greet());

Line 1 has two defaults. Each one does a different job:

  • The = {} at the end is a default for the whole parameter. If the caller passes nothing, the parameter becomes an empty object, {}. Without it, greet() would try to unpack undefined and throw a TypeError. That is the error JavaScript gives when a value is the wrong kind for what you asked it to do.
  • greeting = "Hello" is a default for one property. It fills greeting when the object has no greeting property.

Line 2 uses ??, which picks "friend" when name is undefined or null. Line 4 prints Hello, Mina. Line 5 passes nothing and prints Hello, friend.

Extra properties are allowedPop out in the code editor (opens in a new tab)JavaScript
function showName({ name }) {
  return name;
}
console.log(showName({ name: "Asha", role: "reader" }));

A pattern only needs the properties the function uses. This object also has role, but the pattern names only name. The extra property is ignored, and line 4 prints Asha.

Swapping values

STEP THROUGH

Destructuring can also put values into variables that already exist. You leave out const and let. This is called destructuring assignment. A common use is a swap: each of two variables gets the other's value. You don't need a third variable to hold one value while you swap.

Swap two variables without a third one
Step 0 of 6Ready
Your turn: follow the blue line

The swap works because JavaScript reads the whole right side before it changes the variables on the left.

Running in
  1. script
Next: line 1
let right = "coffee";[left, right] = [right, left];console.log(left, right);
CallStoreChangeResultBlue line: runs next. Ran: already executed.
Recent returnsNothing yet. Start with the blue line.
A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.
Two syntax traps

Two mistakes stop this kind of line from working:

  • An object pattern on existing variables needs round brackets around the whole line: ({ x, y } = point);. Without them, JavaScript reads a { at the start of a line as the start of a block of code, not a pattern. You get a SyntaxError.
  • A line that starts with [a, b] can join onto the line above it if that line has no semicolon. JavaScript then reads the two lines as one, and the swap breaks. End the line above with a semicolon. The lesson Statements, comments & semicolons explains when JavaScript adds semicolons for you.

The order JavaScript follows

STEP THROUGH

Destructuring is short, but it follows fixed rules. Knowing them lets you predict every result:

  1. JavaScript works out the right side of = first.
  2. Then it goes through the pattern from left to right.
  3. A default is used only when the value is undefined.
  4. A default is not even worked out unless it is needed. If the default is a function call, the function runs only when the value is undefined.
The pattern { item = "spare" } used twice. Left: item is undefined, so the box called item gets the default, "spare". Right: item is null, so the box keeps null and the default is skipped.item: undefined"spare"itemdefault useditem: nullnullitemdefault skipped
The same pattern, { item = "spare" }, on two objects. On the left the value is undefined, so the default is used. On the right the value is null, which is a real value, so it is kept.

The step-through below checks the last rule. The function spare() adds 1 to a counter, calls, each time it runs. Change the value on line 6, then watch whether the counter goes up.

When does the default run?
Step 0 of 7Ready
Your turn: follow the blue line

Guess first: will spare() run? Then step through the code to check.

Running in
  1. script
Next: line 1
function spare() {  calls = calls + 1;  return "spare";}const source = { item: undefined };const { item = spare() } = source;console.log(item, calls);
CallStoreChangeResultBlue line: runs next. Ran: already executed.
Recent returnsNothing yet. Start with the blue line.
Change the value of item on line 6

Changing the value starts the step-through again. Watch whether line 3 runs.

A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.
What value does the variable get?
  • const { a = 1 } = { a: undefined };
  • const { a = 1 } = { a: null };
  • const { a = 1 } = {};
  • const { a } = null;
  • const [a = 1] = [];
  • const [a = 1] = [0];
Try it yourself
0 of 6 correct

Sort each line by what the variable gets: the value from the source, the default, or an error before any variable is made.

Choose a category for every card. You can change an answer at any time; Reset clears them all.

Unpacking null or undefined with an object pattern throws a TypeError, because there is no object to read properties from. An array pattern needs an iterable. null and undefined are not iterables either, so that throws too.

Where you will use this

Destructuring makes code that handles a lot of data easier to read. You will use it to:

  • read settings from an options object,
  • take fields out of data from a server,
  • name the key and the value from Object.entries,
  • return two values from a function,
  • swap two variables.

It works best when you already know the shape of the data. Unpack the fields near the top of the function. Then the rest of the function can use short, clear names.

Name each key and value in a loopPop out in the code editor (opens in a new tab)JavaScript
const totals = { apples: 3, oranges: 2 };
for (const [fruit, count] of Object.entries(totals)) {
  console.log(fruit + ": " + count);
}

Object.entries(totals) gives a list of pairs, like ["apples", 3]. Each pair is an array: the key first, then the value. On line 2, the pattern [fruit, count] unpacks each pair. The loop prints apples: 3, then oranges: 2.

Unpack into variables that already existPop out in the code editor (opens in a new tab)JavaScript
let x;
let y;
const point = { x: 4, y: 9 };
({ x, y } = point);
console.log(x, y);

Lines 1 and 2 make x and y with no value yet. Line 4 fills them from point. The round brackets around line 4 are needed, as the "Two syntax traps" box above explains. Line 5 prints 4 9.

Return two values from a functionPop out in the code editor (opens in a new tab)JavaScript
function getCartSummary() {
  return ["tea", 3];
}
const [drink, quantity] = getCartSummary();
console.log(drink + " x " + quantity);

A function can return a small array when two values belong together. On line 4, the caller names the two positions right away. Line 5 prints tea x 3. If you return more values, or the list may grow, an object with named properties is easier to read.

You don't have to destructure

Destructuring is optional. Plain user.profile.name is often better:

  • when you read the value only once,
  • when the object might be missing,
  • when a long pattern would hide where the value comes from.

Use a pattern when you use several fields together and you know the shape of the data.

Common misconceptions

  • "A default replaces any empty-looking value." It replaces only undefined. null, 0, false, and the empty string "" are kept.
  • "Renaming creates both names." { name: fullName } creates only fullName. There is no name variable.
  • "The path in a nested pattern becomes a variable." { address: { city } } creates only city. address is just the way in.
  • "Unpacking an object into existing variables can start a line on its own." It needs round brackets around the whole line: ({ x } = point);.
  • "Array patterns only work on arrays." They work on any iterable, such as a string. Arrays are just the most common.
  • "Destructuring makes a copy." It puts the same values into variables. An object inside the data stays the same object. It is not copied.
  • "You must name every property." A pattern can name only the properties you need. The other properties are ignored.
  • "A longer pattern is always clearer." For a long path, unpack one level first. Then unpack the next object on its own line.

Destructuring does not protect a value from later changes. Say settings.theme holds an object, and you unpack it into a variable called theme. Now theme and settings.theme lead to the same object. If you change that object through one of them, you see the change through the other one too. If you need a separate copy, you have to make it yourself.

When a value might be missing, pick the tool that fits:

  • A default handles a missing property, like { role = "guest" }.
  • Optional chaining, ?., handles a missing object along the way, like user.profile?.name.

They solve different problems. Check the shape of your data first. Don't hide a missing part behind a default.

Practice exercises

5 EXERCISES
Exercise 1 · Warm-upPredict the unpacked values

Read the program. What number does it print?

Starter codePop out in the code editor (opens in a new tab)JavaScript
const scores = [10, 20, 30];
const [first, , third = 99] = scores;
console.log(first + third);

Answer, then press Check. Spacing and letter case don’t matter.

    Exercise 2 · PracticeUnpack a server response

    Use a nested pattern, a rename, and a default to print the user's id, name, and role.

    Starter codePop out in the code editor (opens in a new tab)JavaScript
    const response = { user: { id: 7, name: "Mina" } };
    const { user: { id: userId, name, role = "reader" } } = response;
    console.log(userId, name, role);

    Answer, then press Check. Spacing and letter case don’t matter.

      Exercise 3 · PracticeSwap two variables

      Swap a and b with one destructuring assignment.

      Starter codePop out in the code editor (opens in a new tab)JavaScript
      let a = "left";
      let b = "right";
      [a, b] = [b, a];
      console.log(a, b);

      Answer, then press Check. Spacing and letter case don’t matter.

        Exercise 4 · PracticeFix the crashing function

        Add the missing parameter default, so calling the function with no argument works.

        Starter codePop out in the code editor (opens in a new tab)JavaScript
        function label({ text = "Untitled" }) {
          return text.toUpperCase();
        }
        console.log(label());

        Answer, then press Check. Spacing and letter case don’t matter.

          Exercise 5 · ChallengeUnpack Object.entries in a loop

          Use a pair pattern in the loop. What is the first line it prints?

          Starter codePop out in the code editor (opens in a new tab)JavaScript
          const counts = { apples: 3, oranges: 2 };
          for (const [fruit, count] of Object.entries(counts)) {
            console.log(fruit + "=" + count);
          }

          Answer, then press Check. Spacing and letter case don’t matter.

            Check your understanding

            7 QUESTIONS
            Destructuring quiz · 7 questionsScore: first tries count
            1. Question 1 of 7How does an array pattern choose which value each variable gets?

              Choose an answer to see the explanation.

            2. Question 2 of 7This pattern skips a spot and has a default. What does it print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const [first, , third = 9] = [4, 5];
              console.log(first, third);

              Choose an answer to see the explanation.

            3. Question 3 of 7Which variable does const { name: fullName } = user; create?

              Choose an answer to see the explanation.

            4. Question 4 of 7The value is null and the pattern has a default. What does it print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const { a = "spare" } = { a: null };
              console.log(a);

              Choose an answer to see the explanation.

            5. Question 5 of 7Why does function greet({ name } = {}) end with = {}?

              Choose an answer to see the explanation.

            6. Question 6 of 7This code swaps two variables. What does it print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              let x = "a";
              let y = "b";
              [x, y] = [y, x];
              console.log(x + y);

              Choose an answer to see the explanation.

            7. Question 7 of 7Which line correctly unpacks an object into variables that already exist?

              Choose an answer to see the explanation.

            Key takeaways

            • Array patterns take values by position. Object patterns take values by property name.
            • A default is used only when the value is undefined, and it is worked out only when it is needed.
            • Renaming changes the variable's name. The property keeps its own name.
            • In a nested pattern, the path names are not variables. Only the names at the end become variables.
            • Add = {} to a parameter pattern so the function still works with no argument.
            • Destructuring reads values. It does not copy the objects inside them.
            • When a pattern gets long, or the data might be missing, a shorter pattern or plain property access is clearer.

            Destructuring is a short way to unpack values: the pattern on the left shows which pieces JavaScript should take from the value on the right.

            Before you write a pattern, check three things: the shape of the data, which values might be missing, and whether plain property access would be clearer.

            These checks prevent most destructuring mistakes.

            Up next: Spread & rest.

            CompleteFrontend Clear concepts. Working examples.