Many ways to use Destructuring in Modern JavaScript

Mirza Leka
The Startup
Published in
14 min readJul 4, 2019

Destructuring is without a doubt one of my favorite features of JavaScript language. It’s main purpose is to improve your code and simplify it at the same time.

So, What Is Destructuring?

By the definition, Destructuring allows you to pull one or many properties from an object into a separate variable, but the scope expands beyond that. Destructuring can be used with arrays as well. It can be used within loops, inside functions, to swap variables and much more.
In this article, I’ll introduce you to many ways of using this awesome feature.

Let’s kick things off by creating a simple user object.

const user = { 
fullName: 'Sam Fisher',
age: 62,
job: 'spy'
}

Before Destructuring if we wanted to create a variable and assign it a property, we would do something like this,

const name = user.fullName;
console.log(name) // 'Sam Fisher';

where variable name refers to a fullName property of our user object. Now let’s go through the same example using Destructuring feature:

const { fullName } = user;
console.log(fullName) // 'Sam Fisher';

In this case variable fullName is not only referring to the fullName property, but it only shares the same name. In other words, when we say

const { fullName } = user;

JavaScript is looking for a property within user object named fullName and assigns it to a variable also named fullName.
Pretty neat right? Now let’s pull multiple properties and compare the result.

// Old way:
const fullName = user.fullName;
const age = user.age;
const job = user.job;
console.log(fullName, age, job); // 'Sam Fisher' 62 'spy'
// Destructuring way:
const { fullName, age, job } = user;
console.log(fullName, age, job); // 'Sam Fisher' 62 'spy'

We can clearly see that using Destructuring we simplified the code and replaced three lines of code with just one line!

Keep in mind that any change you make to a property you Destructure will only effect the variable you created, while the property inside an object will remain untouched.

We can also do something like this

const { age, job, fullName } = user;

and output will remain the same:

console.log(fullName, age, job); // 'Sam Fisher' 62 'spy'

When working with objects the order of properties does not matter. What matters is that we match the exact name of each property we are pulling out.

That said, Destructuring can be used for more than just logging variables to the console. Since each property we pull out is a variable just like any other, it can be used same as any other:

const { age } = user;
if ( age < 100 ) {
return 'Hello';
}
return 'World';

But what if name of property is too long or what if we just dislike the name? Can we do something about that? Yes we can and to do that we use,

Alias

When you pull a property out of object, you can give it an alias and then use an alias to refer to that property.

const { fullName: fn } = user;

From here whenever we want to use fullName property, we’ll use fn alias.

console.log(fn); // 'Sam Fisher'

Default Values

When Destructuring properties we can add Default Values to properties that are not defined. Take this example into account:

const user = {
name: undefined
}

It’s obvious that if we log user.name the output will be undefined. In this instance we can set a default value for name property.

const { name = 'Sam' } = user;
console.log(name); // Sam

Now that we know how this works, we can apply this logic for all properties which are not defined.

const user = {
name: 'Sam',
lastName: 'Fisher'
}
const { name, lastName, job = 'spy' } = user;

We gave our user object two properties, name and lastName, but job property is not part of the user object, thus it is not defined. This means that the logic behind Default Values can be applied here.

In a single statement we can pull properties from user object in their own variables and create a new variable, job, and assign it a value.

console.log(name, lastName, job); // 'Sam' 'Fisher' 'spy'

Named Export

If you ever worked with Angular, React or any other JavaScript framework, there is no doubt you’ve encountered a Named Export. Just like Destructuring an object, using import keyword we can choose what of the exports of the module we want to include:

import React, { Component } from 'React';

Here we are importing React into our project, but we are also importing Component from React in it’s own variable named Component. From now on, whenever we want to create a new component, we extend Component, without adding React prefix:

// Old way
import React from 'React';
class MyComponent extends React.Component{}
// New way
import React, { Component } from 'React';
class MyComponent extends Component{}

Same principle applies for any other package we import, for example:

import { isEmail, isCreditCard } from 'validator';

Here we are importing only the functions we want and then use those functions independently:

console.log(isEmail('my@email.com')); // true

Destructuring Array

As mentioned before, in JavaScript we can also Destructure arrays. Concept is nearly the same, but only this time we are using the squared brackets and the order of elements matters.
Let’s create a basic array:

const numbers = [ 10, 20, 30 ];// We can assign each element to a variable
const a = numbers[0];
const b = numbers[1];
const c = numbers[2];
console.log(a); // 10
console.log(b); // 20
console.log(c); // 30

As with objects before, using Destructuring we can pull elements out of the array and store them into variables right away.

const numbers = [ 10, 20, 30 ];
const [ a ] = numbers;
console.log(a); // 10

By wrapping a variable with squared brackets we create an array-like element, where variable a is placed as 0th index and refers to the first element in the numbers array.
Each new variable we add will refer to the next element in the array in that sequence:

const numbers = [ 10, 20, 30 ];
const [ a, b, c ] = numbers;
console.log(a); // 10
console.log(b); // 20
console.log(c); // 30

We can also skip elements using comma:

const numbers = [ 10, 20, 30 ];
const [ a, , b] = numbers;

Variable a is the first element of numbers array, but b is not the second. b is the third element. The comma in between represents the element that was skipped. Therefore:

console.log(a); // 10
console.log(b); // 30

Using spread/rest operator ““ we can target the rest of the elements in array:

const numbers = [ 10, 20, 30 ];
const [ a, ...b ] = numbers;

Variable a will once again be the first element. Variable b has a rest operator prefix, which means that b is an array filled with the rest of the elements in numbers array.

console.log(a); // 10
console.log(b); // [ 20, 30 ];

Please keep in mind that in order for this to work, rest operator can only be assigned to the last element among the variables we are Destructuring.

Default Values

Much like with objects, we can give default values to all array elements that are undefined.

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

Same applies for elements that are not part of the array:

const nums = [ 1, 2, 3 ];
const [ a, b, c, d = 5 ] = nums;
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3
console.log(d); // 5

Variable d is not part of the nums array, thus it’s value is undefined and we can once again apply the logic behind Default Values, create a new variable and assign it a value (in this case 5).

One feature that didn’t make it to Destructuring arrays is Alias. This is not a surprise since when pulling elements from an array, we can name the variables however we like.

Destructuring Function Arguments

Ever had a problem with a long list of parameters you needed to pass into a function? Well say no more, because this one is a game changer.

// Old way
const username = 'SamFisher';
const email ='sam.fisher@thirdechelon.com';
const password ='UqFkD8kCpW';
const age = 62;
const job = 'spy';
funky(username, email, password, age, job);// New way
const user = {
username: 'SamFisher',
email: 'sam.fisher@thirdechelon.com',
password: 'UqFkD8kCpW',
age: 62,
job: 'spy'
};
funky(user);// Alternative
funky({
username: 'SamFisher',
email: 'sam.fisher@thirdechelon.com' ,
password: 'UqFkD8kCpW',
age: 62,
job: 'spy'
});

Rather than passing a long list of properties into a function, we create an object containing those properties and then pass that object as an argument to a function. Then we pull out only the properties we want to use.

// Old way
function funky(username, email, password, age, job) {
console.log(email, password);
}
// New way
function funky({ email: e, password: pw }) {
console.log(e, pw);
}

As seen above, JavaScript is looking for properties email and password inside object we passed as an argument, so again the order doesn’t matter. Adding aliases just simplifies things even further.

This concept works with arrays as well. The idea is to pass an array into a function we are calling and then extract only the elements we want.
Let’s first see how this was handled before Destructuring:

const people = ['Batman', 'Superman', 'Arrow'];function getPerson( arrayOfPeople ) {
console.log(arrayOfPeople[0]); // 'Batman'
console.log(arrayOfPeople[1]); // 'Superman'
console.log(arrayOfPeople[2]); // 'Arrow'
}
getPerson(people);

As seen before, Destructuring allows us to manipulate the data more efficiently and this is how we apply it to previous example:

const people = ['Batman', 'Superman', 'Arrow'];function getPerson( [ a, b, c ] ) {
console.log(a); // 'Batman'
console.log(b); // 'Superman'
console.log(c); // 'Arrow'
}
getPerson(people);

Each element in array argument represents an element from people array at that index. We can once again use rest operator to target the rest of the array:

function getPerson( [ a, ...b ] ) {
console.log(a); // 'Batman'
console.log(b); // [ 'Superman', 'Arrow' ]
}
getPerson(people);

Destructuring Return Statement

Just like with function arguments, we can Destructure values that function is returning. This can be applied for functions that are returning an object or an array.
Case 1: Function returns an object

function getUserDetails() {
return { name: 'Sam Fisher', age: 62, job: 'spy' }
}
const { name } = getUserDetails();
console.log(name); // 'Sam Fisher'

Case 2: Function returns an array

function getAvengers() {
return ['Ironman', 'Captain America', 'Thor', 'Hulk']
}
const [ a, , , b ] = getAvengers();// Notice that I created two commas in the middle. This means that I'm skipping both Captain America and Thorconsole.log(a); // 'Ironman'
console.log(b); // 'Hulk'

As simple as that.

Destructuring Inside a Loop

So far we’ve seen many uses of Destructuring, but one topic we haven’t touched yet are the loops. Let’s start by creating an array and then use for of loop to iterate over that array.

const numbers = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ];for (let num of numbers) {
console.log(num);
}
// [ 1, 2, 3 ]
// [ 4, 5, 6 ]
// [ 7, 8, 9 ]

For each inner array inside numbers array we print that iteration of the array.
Now let’s apply Destructuring and pull elements out of each iteration. Then we get something like this:

const numbers = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ];for (let [ a, b, c ] of numbers) {
console.log(a, b, c);
}
// 1 2 3
// 4 5 6
// 7 8 9

Pretty cool huh?
Here is another example combined with Default Values.

const simpsons = [
{ name: 'Homer', age: 36 },
{ name: 'Marge', age: 34},
{ name: 'Bart' },
{ name: 'Lisa', age: 7 },
{ name: 'Maggie' }
];

It’s obvious that some objects don’t have the age property. We can loop through all objects and instead of returning undefined for each user without age property, we can give those users an age with default value of 0.

for (let { name, age = 0 } of simpsons ) {
console.log(name, age);
}
// 'Homer' 36
// 'Marge' 34
// 'Bart' 0
// 'Lisa' 7
// 'Maggie' 0

Destructuring Nested Objects and Arrays

Destructuring simplifies the way we write JavaScript, but that does not mean Destructuring is meant for simple uses.

Destructuring nested objects

Consider this fake weather API data:

const weatherData = {
city: 'London',
temperature: {
minimum: 10,
expected: 30,
current: 25
}
}

Think about building a Weather App and use a previous API to present the current temperature to user. You could write down
weatherData.temperature.current, but instead you can apply Destructuring.

Let’s unwrap this API data step by step.
We start by pulling out a temperature object and assign it to it’s parent object, weatherData:

const { temperature } = weatherData;

Then in between the two we place another property or a group of properties we wish to pull out and surround them with another pair of curly braces.
Then we get something that looks like this,

const { temperature: { current } } = weatherData;

where current is a property of temperature object and temperature is a property of weatherData object.
Now that we’ve created a variable named current, we can use it however we like.

console.log(current); // output: 25

We can also use an alias here.

const { temperature: { current: c, expected: e } } = weatherData;
console.log(c); // output: 25
console.log(e); output: 30

If property has an undefined value we can give it a default one or if it does not even exist in our object, we can create it like a Destructured variable,

const { temperature: { likelyNot: LN = 9999 } } = weatherData;
console.log(LN); // output: 9999

where LN is an alias to likelyNot.

The same concept can be applied to more deeply nested objects.

const weatherData = {
city: 'London',
temperatureCelsius: {
minimum: 10,
expected: 30,
current: 25
},
temperatureFahrenheit: {
minimum: 50,
expected: 86,
current: 77
}
}

Now let’s pick up current temperature from both objects.

oonst { 
temperatureCelsius: { current: currentC },
temperatureFahrenheit: { current: currentF }
} = weatherData;
console.log(currentC); // output: 25
console.log(currentF); // output: 77

Notice that I’m using aliases here to avoid conflict of having two different temperature variables which share the same name.

Destructuring nested arrays

Nested arrays are common in JavaScript and working with them has significantly been simplified with Modern JavaScript.
Take this array of heroes into a count:

const heroes = [
[ 'Spiderman', 'Iron Man', 'Captain America' ],
['Batman', 'Superman', 'Wonder Woman']
]

Let’s extract Marvel and DC heroes into two separate arrays:

const [ marvel, dc ] = heroes;console.log(marvel); 
// output: [ 'Spiderman', 'Iron Man', 'Captain America' ]
console.log(dc);
// output: ['Batman', 'Superman', 'Wonder Woman']

Now let’s take this example one step further and add another array within our heroes array. Inside our inner array we’ll define one property and in this case it will refer to the first element of first inner array.

const [ [ spider ] ] = heroes;
console.log(spider); // output: 'Spiderman'

Just like before we can use commas to skip the array elements. Let’s extract the last element from the first array.

const [ [ , , captain ] ] = heroes
console.log(captain); // output: 'Captain America'

If we add another inner array in our outer (heroes) array, separated from the first inner array (Marvel) by comma, it will refer to an array of DC heroes. From there we can extract one or more heroes from the DC array.

const [ [ , , captain ], [ bat ] ] = heroes
console.log(captain); // output: 'Captain America'
console.log(bat); // output: 'Batman'

An alternative to Destructuring nested arrays would be to use ES9 Array.flat() function, whose purpose is to flat the nested array into a normal one.

const flatten = heroes.flat();
console.log(flatten);
// output: [ 'Spiderman', 'Iron Man', 'Captain America', 'Batman', 'Superman', 'Wonder Woman']

Then we can select our heroes like we’d from normal array:

const [ spider, , captain, bat] = flatten;console.log(spider); // output: 'Spiderman'
console.log(captain); // output: 'Captain America'
console.log(bat); // output: 'Batman'

Destructuring nested function arguments

Imagine we want to handle a change event on an HTML element and we want to grab a value we type.

<input type="text" onchange="handleChange(event)"/>

Using nested Destructuring we can extract a target object from an event object and then extract a value property from target:

# 1
function handleChange(event) {
const { value } = event.target;
console.log(value);
}
# 2
function handleChange({ target }) {
const { value } = target;
console.log(value);
}
# 3
function handleChange({ target: { value } }) {
console.log(value);
}

Same goes for nested arrays.

const nestedArray = [ [ 'A', 'B', 'C' ], [ 'D', 'E', 'F' ] ];
handleNestedArray(nestedArray);
# 1
function handleNestedArray(full) {
console.log(full); // output: [ ['A', 'B', 'C'], ['D', 'E', 'F'] ]
}
# 2
function handleNestedArray([ firstArray ]) {
console.log(firstArray); // output: ['A', 'B', 'C']
}
# 3
function handleNestedArray([ [], [ , letterE ] ]) {
console.log(letterE); // output: 'E'
}

Destructuring nested return statement

If you’re dealing with a function that returns a nested array or an object, you can take advantage of Destructuring to pull out only the properties you need.

function handleObject() { 
return { target: { value: 'Hello' } };
}
# 1
const result = handleObject();
console.log(result); // output: { target: { value: 'Hello' } }
# 2
const { target } = handleObject();
console.log(target); // output: { value: 'Hello' }
# 3
const { target: { value } } = handleObject();
console.log(value); // output: 'Hello'

And this applies to arrays as well.

function handleArray() {
return [ [ 1, 2], [3, 4] ];
}
# 1
const fullArray = handleArray();
console.log(fullArray); // output: [ [ 1, 2], [3, 4] ]
# 2
const [ first ] = handleArray();
console.log(first); // output: [1, 2]
# 3
const [ [ one, two ] ] = handleArray();
console.log(one, two); // output: 1, 2

Swapping variables with Destructuring

Using Destructuring assignment we can do just that, swap variables! However, this isn’t restricted to just numbers. We can swap any types, two strings, two arrays, two objects, etc. In some cases we can even swap variables that are different types.

// Let's declare two variables
let hero = 'Mario';
let villain = 'Bowser';
console.log(hero, villain); // 'Mario' 'Bowser'
// Now let's swap them
[ hero, villain ] = [ villain, hero ];
console.log(hero, villain); // 'Bowser' 'Mario'

We wrap both variables in square brackets and assign them another pair of wrapped variables, only second time we switch places. This causes variables to switch values and suddenly Bowser becomes the hero and Mario becomes the villain!

Destructuring in Day to Day uses

When I write code, I tend to use Destructuring whenever possible.
Did you know that you can Destructure a console.log?

const { log, warn, error } = console;log('Hello World!'); // equivalent to console.log('...');
warn('Watch out!'); // console.warn('...');
error('Something went wrong!'); // console.error('...');

Since console is an object you can Destructure it’s properties the same way you’d for any other object.
But you can also Destructure properties of HTML elements.

const { value } = document.querySelector('input');

This way it’s much easier to pull a value property out of an input, just as pulling disabled property out of a button.

const { disabled } = document.querySelector('button');

Same applies for all other properties.

Wrapping up

I hope you had fun reading this article as well as learned something new about this amazing feature of Modern JavaScript. If you are interested to learn more, there is a gist full of examples like these written by Mikael Brevik and if you have any questions, let me know in the comments below.

--

--

Mirza Leka
The Startup

Web Developer. DevOps Enthusiast. I share my experience with the rest of the world. Follow me on https://twitter.com/mirzaleka for news & updates #FreePalestine