JavaScript's Destructuring Assignment

Introduction

If you wanted to select elements from an array or object before the ES2015 update to JavaScript, you would have to individually select them or use a loop.

The ES2015 specification introduced the destructuring assignment, a quicker way to retrieve array elements or object properties into variables.

In this article, we'll use the destructuring assignment to get values from arrays and objects into variables. We'll then see some advanced usage of the destructuring assignment that allows us to set default values for variables, capture unassigned entries, and swap variables in one line.

Array Destructuring

When we want to take items from an array and use them in separate variables, we usually write code like this:

let myArray = [1, 2, 3];
let first = myArray[0];
let second = myArray[1];
let third = myArray[2];

Since the major ES2015 update to JavaScript, we can now do that same task like this:

let myArray = [1, 2, 3];
let [first, second, third] = myArray;

The second, shorter example used JavaScript's destructuring syntax on myArray. When we destructure an array, we are copying the values of its elements to variables. Array destructuring syntax is just like regular variable assignment syntax (let x = y;). The difference is that the left side consists of one or more variables in an array.

The above code created three new variables: first, second, and third. It also assigned values to those variables: first is equal to 1, second is equal to 2, and third is equal to 3.

With this syntax, JavaScript sees that first and 1 have the same index in their respective arrays, 0. The variables are assigned values corresponding to their order. As long as the location matches between the left and right side, the destructuring assignment will be done accordingly.

The destructuring syntax also works with objects, let's see how.

Object Destructuring

Before the destructuring syntax was available, if we wanted to store an object's properties into different variables we would write code like this:

const foobar = {
    foo: "hello",
    bar: "world"
};

const foo = foobar.foo;
const bar = foobar.bar;

With the destructuring syntax, we can now quickly do the same thing with fewer lines of code:

const foobar = {
    foo: "hello",
    bar: "world"
};

const { foo, bar } = foobar;

While array items are destructured via their position, object properties are destructured by their key name. In the above example, after declaring the object foobar we then create two variables: foo and bar. Each variable is assigned the value of the object property with the same name. Therefore foo is "hello" and bar is "world".

Note: The destructuring assignment works whether you declare a variable with var, let, or const.

If you prefer to give a different variable name while destructuring an object, we can make a minor adjustment to our code:

const foobar = {
    foo: "hello",
    bar: "world"
};

const { foo: baz, bar } = foobar;
console.log(baz, bar); // hello world

With a colon, we can match an object property and give the created variable a new name. The above code does not create a variable foo. If you try to use foo you will get a ReferenceError, indicating that it was not defined.

Now that we've got the basics of destructuring arrays and objects, let's look at some neat tricks with this new syntax. We'll start with our option to select default values.

Default Values in Destructured Variables

What happens if we try to destructure more variables than the number of array elements or object properties? Let's see with a quick example:

let [alpha1, alpha2, alpha3] = ['a', 'b'];

console.log(alpha1, alpha2, alpha3);

Our output will be:

a b undefined

Unassigned variables are set to undefined. If we want to avoid our destructured variables from being undefined, we can give them a default value. Let's reuse the previous example, and default alpha3 to 'c':

let [alpha1, alpha2, alpha3 = 'c'] = ['a', 'b'];

console.log(alpha1, alpha2, alpha3);

If we run this in node or the browser, we will see the following output in the console:

a b c

Default values are created by using the = operator when we create a variable. When we create variables with a default value, if there's a match in the destructuring environment it will be overwritten.

Let's confirm that's the case with the following example, which sets a default value on an object:

const { prime1 = 1, prime2 } = { prime1: 2, prime2: 3 };

console.log(prime1, prime2);

In the above example, we default prime1 to 1. It should be overwritten to be 2 as there is a prime1 property on the object in the right-hand side of the assignment. Running this produces:

2 3
Free eBook: Git Essentials

Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!

Great! We've confirmed that default values are overwritten when there's a match. This is also good because the first prime number is indeed 2 and not 1.

Default values are helpful when we have too little values in the array or object. Let's see how to handle cases when there are a lot more values that don't need to be variables.

Capturing Unassigned Entries in a Destructured Assignment

Sometimes we want to select a few entries from an array or object and capture the remaining values we did not put into individual variables. We can do just that with the ... operator.

Let's place the first element of an array into a new variable, but keep the other elements in a new array:

const [favoriteSnack, ...fruits] = ['chocolate', 'apple', 'banana', 'mango'];

In the above code, we set favoriteSnack to 'chocolate'. Because we used the ... operator, fruits is equal to the remaining array items, which is ['apple', 'banana', 'mango'].

We refer to variables created with ... in the destructuring assignment as the rest element. The rest element must be the last element of the destructuring assignment.

As you may have suspected, we can use the rest element in objects as well:

const { id, ...person } = {
    name: 'Tracy',
    age: 24,
    id: 1020212,
};

We extract the id property of the object on the right-hand side of the destructuring assignment into its own variable. We then put the remaining properties of the object into a person variable. In this case, id would be equal to 1020212 and person would be equal to { name: 'Tracy', age: 24 }.

Now that we've seen how to keep all the data, let's see how flexible the destructuring assignment is when we want to omit data.

Selective Values in a Destructuring Assignment

We don't have to assign every entry to a variable. For instance, if we only want to assign one variable from many options we can write:

const [name] = ['Katrin', 'Judy', 'Eva'];
const { nyc: city } = { nyc: 'New York City', ldn: 'London' };

We assigned name to 'Katrin' from the array and city to 'New York City' from the object. With objects, because we match by key names it's trivial to select particular properties we want in variables. In the above example, how could we capture 'Katrin' and 'Eva' without having to take 'Judy' as well?

The destructuring syntax allows us to put holes for values we aren't interested in. Let's use a hole to capture 'Katrin' and 'Eva' in one go:

const [name1, , name2] = ['Katrin', 'Judy', 'Eva'];

Note the gap in the variable assignment between name1 and name2.

So far we have seen how flexible the destructuring assignment can be, albeit only with flat values. In JavaScript, arrays can contain arrays and objects can be nested with objects. We can also have arrays with objects and objects with arrays. Let's see how the destructuring assignment handles nested values.

Destructuring Nested Values

We can nest destructuring variables to match nested entries of an array and object, giving us fine-grained control of what we select. Consider having an array of arrays. Let's copy the first element of each inner array into their own variable:

let [[part1], [part2], [part3], [part4]] = [['fee', 'mee'], ['fi', 'li'], ['fo', 'ko'], ['fum', 'plum']];

console.log(part1, part2, part3, part4);

Running this code will display the following output:

fee fi fo fum

By simply wrapping each variable in the left-hand side with [], JavaScript knows that we want the value within an array and not the array itself.

When we destructure nested objects, we have to match the key of the nested object to retrieve it. For example, let's try to capture some details of a prisoner in JavaScript:

const {
    name,
    crimes: {
        yearsToServe
    }
} = {
    name: 'John Doe',
    crimes: {
        charged: ['grand theft auto', 'stealing candy from a baby'],
        yearsToServe: 25
    }
};

console.log(yearsToServe);

To get the yearsToServe property, we first need to match the nested crimes object. In this case, the right-hand side has a yearsToServe property of the crimes object set to 25. Therefore, our yearsToServe variable will be assigned a value of 25.

Note that we did not create a crimes object in the above example. We created two variables: name and yearsToServe. Even though we must match the nested structure, JavaScript does not create intermediate objects.

You've done great so far in covering a lot of the destructured syntax capabilities. Let's have a look at some practical uses for it!

Use Cases for Destructuring Arrays and Objects

There are many uses for destructuring arrays and object, in addition to the lines of code benefits. Here are a couple of common cases where destructuring improves the readability of our code:

For Loops

Developers use the destructuring assignment to quickly pull values of interest from an item in a for loop. For example, if you wanted to print all the keys and values of an object, you can write the following:

const greetings = { en: 'hi', es: 'hola', fr: 'bonjour' };

for (const [key, value] of Object.entries(greetings)) {
    console.log(`${key}: ${value}`);
}

First, we create a greetings variable that stores how to say "hello" in different languages. Then we loop through the values of the object using the Object.entries() method which creates a nested array. Each object property is represented by 2 dimensional array with the first item being the key and the second item being its value. In this case, Object.entries() creates the following array [['en', 'hi'], ['es', 'hola'], ['fr', 'bonjour']].

In our for loop, we destructure the individual arrays into key and value variables. We then log them to the console. Executing this program gives the following output:

en: hi
es: hola
fr: bonjour

Swapping Variables

We can use the destructuring syntax to swap variables without a temporary variable. Let's say you're at work and taking a break. You wanted some tea, while your coworker wanted some coffee. Unfortunately, the drinks got mixed up. If this were in JavaScript, you can easily swap the drinks using the destructuring syntax:

let myCup = 'coffee';
let coworkerCup = 'tea';
[myCup, coworkerCup] = [coworkerCup, myCup];

Now myCup has 'tea' and coworkerCup has 'coffee'. Note how we did not have let, const, or var when using the destructuring assignment. As we aren't declaring new variables, we need to omit those keywords.

Conclusion

With the destructuring assignment, we can quickly extract values from arrays or objects and put them into their own variables. JavaScript does this by matching the variable's array position, or the name of the variable with the name of the object property.

We've seen that we can assign default values to variables we are creating. We can also capture the remaining properties of arrays and objects using the ... operator. We can skip entries by having holes, which are indicated by commas with nothing in between them. This syntax is also flexible enough to destructure nested arrays and objects.

We provided a couple of nifty places to use the destructuring assignment. Where will you use them next?

Last Updated: February 19th, 2020
Was this article helpful?

Improve your dev skills!

Get tutorials, guides, and dev jobs in your inbox.

No spam ever. Unsubscribe at any time. Read our Privacy Policy.

© 2013-2024 Stack Abuse. All rights reserved.

AboutDisclosurePrivacyTerms