ES6 - Understanding Destructuring
Tags: 100daysofcode, javascript, codenewbie, webdev
Published: 2020-07-10 15:52:26

# Introduction

Destructuring is a very powerful feature that was introduced with ES6 version of JavaScript. This article will provide a comprehensive overview about everything that you'll need to know about Destructuring.

- Why Destructuring?
- What is Destructuring?
- Object Destructuring
- Array Destructuring
- Mixed Destructuring
- Function Destructuring

# Why Destructuring?

If you have been coding in JavaScript, you would have come across scenarios where you would have to access nested objects. Especially, this is true in the case when  integrating your application with the third-party APIs. You will often have to work with the JSON response received from the API and the object structure is often complex with nested elements.

Accessing the complex nested elements of objects is precisely 'Why' we should use destructuring. It provides a way to simplify extraction of complex structure.

Let us take a look at the following code example:

```jsx
//Employee Variable containing nested address for Home and Work
const employee = {
  name: 'Skay',
  age: 32,
  address: {
      line1: '1480 Rachel Garden',
      city: 'Pine Brook',
      state: 'NJ',
      country: 'USA',
  }
};

//Function displays the Home Address individually
function displayHomeAddress(employee) {
	console.log(`The name of the employee is ${employee.name}`);
  console.log(`The Home Address line 1 is ${employee.address.line1}`);
  console.log(`The Home City is ${employee.address.city}`);
  console.log(`The Home State is ${employee.address.state}`);
  console.log(`The Home Country 1 is ${employee.address.country}`);
}

//Call the displayHomeAddress() function
displayHomeAddress(employee);

/*
The name of the employee is Skay
The Home Address line 1 is 1480 Rachel Garden
The Home City is Pine Brook
The Home State is NJ
The Home Country 1 is USA
*/
```

Two main things to observe from the above code example:

1. The way to access the values inside nested objects leads to more code being typed at each point of access.
2. The probability of having a typo is more while trying to type out longer sentences to access nested elements inside the object. 

While this might not seem much of a problem with a single file, typically in a real life project with large code base, you'll be dealing with a lot of nested objects and with the destructuring the same can be achieved with a much simpler, compact syntax.

# What is Destructuring?

In JavaScript, while using objects & arrays, we would often have to deal with complex structures. Destructuring is the process of breaking down such complex structures into simpler parts.

Using destructuring, the above code snippet, will look like this:

```jsx
const employee = {
  name: 'Skay',
  age: 32,
  address: {
      line1: '1480 Rachel Garden',
      city: 'Pine Brook',
      state: 'NJ',
      country: 'USA',    
  }
};

// Object Destructuring - The left hand side represents the elements that need to be extracted from the parent element
// The right hand side references the parent complex element from which values need to be extracted
const { name } = employee;
const { line1, city, state, country } = employee.address;

function displayHomeAddress(employee) {
  console.log(`The name of the employee is ${name}`);
  console.log(`The Home Address line 1 is ${line1}`);
  console.log(`The Home City is ${city}`);
  console.log(`The Home State is ${state}`);
  console.log(`The Home Country 1 is ${country}`);
}

displayHomeAddress(employee);

/*
The name of the employee is Skay
The Home Address line 1 is 1480 Rachel Garden
The Home City is Pine Brook
The Home State is NJ
The Home Country 1 is USA
*/
```

Couple of things to note:

- The element to be extracted has to be placed in between curly parentheses {}.
- Destrucutring syntax can be expressed as { elementTobeExtracted } = 'parentElement' . Where the elementTobeExtracted must be a direct child of the Parent Element.
- In the above example, 'name' is a direct child of 'employee' element. Likewise, the variables 'line1', 'city', 'state' and 'country' are direct children of the element 'address' which is accessed using the dot operator. (employee.address)

# Object Destructuring

The above code snippet was an example of object destructuring. Let us look at an another example, so that, we can really reinforce the concepts.

```jsx
//Person object - Simple (No nesting)
const person = {
  name: 'Skay',
  age: 38,
  skills: 'JavaScript',
};

// Object Destructuring
const { name, age, skills } = person;

//Display the output to the console
console.log(name, age, skills);

//Output -> Skay 38 JavaScript
```

As we have seen above, the left hand side is an assignment expression where we have used an object literal to extract the direct child elements from the parent element person.

Let us take another code example, where we can use object destructuring for variable assignment.

```jsx
//Employee Object containing the name, age and skills as atrributes
const employee = {
  name: 'John',
  age: 25,
  skills: 'HTML CSS',
};

// Object Destructuring - It is assigned to a 'let' and not a 'const' for reassignment
let { name, age, skills } = employee;

//Display the output to the console
console.log(name, age, skills);

//Output -> John 25 HTML CSS

//Employee Object also containing the name, age and skills as atrributes
const person = {
  name: 'Skay',
  age: 38,
  skills: 'JavaScript',
};

// Object Destructuring - Reassigning the 'name' 'age' and 'skills' to the new values extracted from person object
({ name, age, skills } = person);

//Display the output to the console
console.log(name, age, skills);

//Output -> Skay 38 JavaScript
```

Things to note:

- Initially, the values 'name', 'age' and 'skills' were destructured from the 'employee' object.
- The desturctured values were assigned to the variables (let) name, age and skills.
- Immediately, again using destructuring we have extracted the values name, age and skills from the 'person' object and reassigned to the 'name', 'age', 'skills' variables.
- The use of enclosing parentheses (()) in the assignment expression of 'name', 'age' and 'skills' were necessary, since, we are doing an assignment operation. If omitted, the destructuring object literal will be considered as a block statement and will throw an error.
- To summarize, we have reassigned new values to the local variables name, age and skills through destructuring.

## Default Values

We can assign default values to variable while destructuring. Failing to do so, will cause the value 'undefined' to be assigned to the destructured variable.

```jsx
const person = {
  name: 'Skay',
  age: 38
};

// Assign default value of Canada to country if undefined
const { name, age, country = 'Canada' } = person;

// Here I am using ES6 template literals
console.log(`I am ${name} from ${country} and I am ${age} years old.`);

// Output -> I am Skay from Canada and I am 38 years old.'
```

In the above example, 'country' was not defined with the 'person' object and it was assigned a default value of 'Canada' during destructuring.

However, if an actual value is passed for 'country' to the 'person' object, then the default value will not be displayed as shown in the code snippet below.

```jsx
const person = {
  name: 'Skay',
  age: 38,
	country: 'India'
};

// Assign default value of Canada to country if undefined
const { name, age, country = 'Canada' } = person;

// Here I am using ES6 template literals
console.log(`I am ${name} from ${country} and I am ${age} years old.`);

// Output -> I am Skay from India and I am 38 years old.'
```

## Using Different Variable Names while Destructuring

In the examples we've seen so far, we've used the variable names match the corresponding object key. However it is possible to use a different name for variables during destructuring using the following sytax.

Syntax for using different variable name → [object_key] : [variable_name]

Let us look at the below code example:

```jsx
const person = {
  name: 'Skay',
  age: 38,
	country: 'India'
};

// Assign default value of Canada to country if undefined
const { name: fullName, age: years, country: place = 'Canada' } = person;

// Here I am using ES6 template literals
console.log(`I am ${fullName} from ${years} and I am ${place} years old.`);

// Output -> I am Skay from India and I am 38 years old.'
```

Things to note:

- The variables 'name', 'age' and 'country' were extracted from the object person and were assigned to 'fullName', 'years' and 'country' respectively.
- Default value assignment is used in conjunction with assigning to a different variable.

## Nested Object Destructuring

If we look at the first example in this article, we had the employee object with address field that contained nested elements.

In the example, I had demonstrated the usage of destructuring through two individual lines of code as shown below:

```jsx
const { name } = employee;
const { line1, city, state, country } = employee.address;
```

We can combine the destructuring in a single line as shown below. This is referred to as Nested Destructuring.

```jsx
const {  name, address: { line1, city, state, country } } = employee;
```

Here's the complete code snippet that you can run for the nested destructuring scenario.

```jsx
//Employee Object containing nested elements
const employee = {
  name: 'Skay',
  age: 32,
  address: {
    line1: '1480 Rachel Garden',
    city: 'Pine Brook',
    state: 'NJ',
    country: 'USA'
  },
};

// Nested Object Destructuring - Use the child element 'address' as a reference 
// to further destructure to get nested inner elements line1, city, state & country
const {  name, address: { line1, city, state, country } } = employee;

function displayHomeAddress(employee) {
  console.log(`The name of the employee is ${name}`);
  console.log(`The Home Address line 1 is ${line1}`);
  console.log(`The Home City is ${city}`);
  console.log(`The Home State is ${state}`);
  console.log(`The Home Country 1 is ${country}`);
}

displayHomeAddress(employee);
```

I think with this, we've covered all that this there related to Object destructuring. Let us dive into Array destructuring.

# Array Destructuring

Array destructuring is very similar to object destructuring. Let us look the below example.

```jsx
// A const representing rgb
const animal = ['cat', 'dog', 'rat'];

// Array Destructuring
const [cat, dog, rat] = animal;

//Display the value of R, G, B on the console
console.log(`${cat}, ${dog}, ${rat}`); 

// Output -> cat, dog, rat
```

Things to note:

- The variables cat, dog and rat have been assigned the values of 'cat', 'dog' and 'rat' through array destructuring of animal array.
- Each variable is mapped to the corresponding item at the same index on the 'animal' array.

## Default Values

Exactly like how we do default value assignment to Object destructuring, we can do for array destructuring as well.

```jsx
// A const representing rgb
const animal = ['cat', 'dog'];

// Array Destructuring - Default value assignment
const [cat, dog, rat = 'rat'] = animal;

//Display the value of R, G, B on the console
console.log(`${cat}, ${dog}, ${rat}`);

// Output -> cat, dog, rat
```

In the above example, the variable rat has been set a default value of 'rat' at the step of destructuring.

## Destructure selected elements from the Array

We can use the power of destructuring to select a specified set of elements from an array. Let us look at another code example.

```jsx
//Numbers array
const numbers = [100, 200, 300, 400, 500];

//Skip the elements that you do not want to extract
const [, , three, four] = numbers;

//Display on the console
console.log(three, four);

//Output -> 300 400
```

In the above example, we can skip the elements that we do not want to extract from the parent array. We used comma separator to omit the first, second and last items in the array.

## Nested Array Destructuring

Just like how we were able to do a nested destructuring of objects, we can do the same with the arrays as well. Let us look at the below code example.

```jsx
//Const Color contains hex code and a nested array of rgb values
const color = ['#FF00FF', [255, 0, 255]];

// Use nested destructuring to assign red, green and blue
const [hex, [red, green, blue]] = color;

console.log(hex, red, green, blue); 
//Output -> #FF00FF 255 0 255
```

In the above example, the rgb values are nested arrays and similar to object destructuring, using the square parentheses, we are able to access elements nested inside the parent.

# Mixed Destructuring

Let us combine the power of both object & array & nested destructuring which might be the case if you are dealing with complex objects like the example shown below:

```jsx
//Const Person contains nested elements of objects & arrays
const person = {
  name: 'Skay',
  location: {
    city: 'Mumbai',
    country: 'India',
    latlong: [19.07609, 72.877426],
  },
};

// We are assigning 5 variables: name, country, city, lat, lng
// We are combining object, nested object & array destructuring in a single line
const {
  name,
  location: {
    city,
    country,
    latlong: [lat, lng],
  },
} = person;

console.log(
  `I am ${name} from ${city}, ${country}. Latitude(${lat}), Longitude(${lng})`
);

// Output -> I am Skay from Mumbai, India. Latitude(19.07609), Longitude(72.877426)
```

Things to note:

- 'name' variable is assigned by using object destructuring. It is a direct child of the 'person' object.
- The variable 'city', 'country' and 'latlong' are accessed using nested destructuring.
- The 'latlong' within the 'person' object is an array which is further destructured using the array destructuring syntax and assigned to the 'lat' and 'long' variables.

# Function Destructuring - Applied to the parameters passed in

For folks who have used React and who will get into learning ReactJS, this is one thing you'll observe quiet a bit. We can apply destructuring to the parameters of a function as shown in the code example below.

```jsx
//Employee Object containing nested elements
const employee = {
  name: 'Skay',
  age: 38,
  skills: {
    languages: 'JavaScript, HTML, CSS',
    databases: 'MySQL, PostgreSQL, MongoDB',
  },
};

//The person object is destructured within the parameters of the function that is passed in
//We have used both object & nested object destructuring within the function parameters
function displayEmployeeInfo({ name, age, skills: { languages, databases } }) {
  console.log(
    `The employee name is ${name} & his age is ${age}. He knows the following languages - ${languages} and is familiar with the databases - ${databases}`
  );
}

//We are invoking the function displayEmployeeInfo & passing in the 'employee' object
displayEmployeeInfo(employee);
//Output -> The employee name is Skay & his age is 38. He knows the following 
//languages - JavaScript, HTML, CSS and is familiar with the databases - MySQL, 
//PostgreSQL, MongoDB
```

In the above example, the 'employee' object is destructured (nested destructuring is also applied) within the parameters of the function 'displayEmployeeInfo' and the variable name, age, languages & databases are assigned.

An important thing to note that if the 'destructured parameter' is omitted, it'll throw an error. In the above example, if we invoke the displayEmployeeInfo() without passing the employee object, it'll throw an error.

```jsx
//Invoking the displayEmployeeInfo() without a function will output the error
displayEmployeeInfo();

//Output -> Uncaught TypeError: Cannot destructure property 'name' of 'undefined' as 
//it is undefined.
```

We can assign a fallback object literal as a default value to handle the error. So, the above code example would need to be modified below to handle the function being invoked without a parameter.

```jsx
//Employee Object
const employee = {
  name: 'Skay',
  age: 38,
  skills: {
    languages: 'JavaScript, HTML, CSS',
    databases: 'MySQL, PostgreSQL, MongoDB',
  },
};

//Object destructuring and nested object destructuring with default value of object literal
function displayEmployeeInfo({
  name,
  age,
  skills: { languages, databases } = {},
} = {}) {
  console.log(
    `The employee name is ${name} & his age is ${age}. He knows the following languages - ${languages} and is familiar with the databases - ${databases}`
  );
}

//Invoke the displayEmployeeInfo() without passing in the employee object
displayEmployeeInfo();

//Output -> The employee name is undefined & his age is undefined. 
//He knows the following languages - undefined and is familiar with the databases - undefined
```

Assigning the default object literal '{}' will handle the function call gracefully.

# Conclusion

I think we've covered all that is there to know about destructuring in JavaScript. I think it's a powerful feature that improves maintainability and readability. In addition, it reduces the repetition of typing long statements to access nested variables.

To summarize, we have gone through the following concepts of destructuring in this article:

- Object Destructuring
- Nested Destructuring
- Array Destructuring
- Function Destructuring
- Mixed Destructuring

I hope you enjoyed the article. As always, let me know your comments & feedback and do share it with your friends.

You may also be interested in the following:
- [Understanding Closures](https://dev.to/skaytech/understanding-closures-1501)
- [Understanding Hoisting] (https://dev.to/skaytech/understanding-hoisting-b48)
- [Async/Await] (https://dev.to/skaytech/async-functions-chapter-3-async-await-89)
- [Promises] (https://dev.to/skaytech/async-functions-chapter-2-promises-1c6i)
- [Immediately Invoked Function Expressions](https://dev.to/skaytech/iife-immediately-invoking-function-expressions-1164)
- [Module & Revealing Module Design Patterns](https://dev.to/skaytech/js-design-patterns-module-revealing-module-pattern-30c6)
- [History of ECMAScript](https://dev.to/skaytech/history-of-ecma-es5-es6-beyond-lpe)