JS: Destructuring
Tags: javascript, destructure, destructuring
Published: 2021-07-02 08:18:30

## A deep dive into the powerful world of javascript destructuring

> Jump to:
- [Array Destructuring](#array-destructuring-anchor)
- [Combining 2 Arrays](#combining-2-arrays-anchor)
- [Destructuring with Functions](#destructuring-with-functions-anchor)
- [Destructuring with Default Values](#destructuring-with-default-values-anchor)
- [Object Destructuring](#object-destructuring-anchor)

---

# Array Destructuring <a name="array-destructuring-anchor"></a>

Take the arrays called alphabet and numbers below.

```javascript
const alphabet = ['A', 'B', 'C', 'D', 'E', 'F']
const numbers = [1, 2, 3, 4, 5, 6]
```

To destructure alphabet, you simply set what you want to destructure equal to the name of the array as follows:

```javascript
const [a, b, c] = alphabet
```

Note that we wrap a, b and c in square brackets purely because we are destructuring an array. Had we been destructuring an object, they'd be wrapped in curly braces { }. _We'll touch more on this later on._
For now, we have destructured the first 3 elements of the alphabet array, into variables called a, b and c. To prove this, if we run the below:

```javascript
console.log(a);
console.log(b);
console.log(c);
```
We would get back in our development console:
```javascript
A
B
C
```

## What if I want to skip element?
If you wanted to, for example, skip the second element, you could simply leave an empty comma , when destructuring per below:
```javascript
const [a,, c] = alphabet
```
Now logging the following:
```javascript
console.log(a);
console.log(b);
console.log(c);
```
Would return:
```javascript
A
C
```
## What if I want the rest of the array?
If you wanted to print the rest of the array while destructuring, because maybe you want to return the array without the first element for example, you can do this by combining the **spread operator ...**
```javascript
const alphabet = ['A', 'B', 'C', 'D', 'E', 'F']
const [,b, ...restOfTheElements] = alphabet
```
So in the above example, we destructure the alphabet on the second line, skipping the first element (as marked by the empty comma ,) then we assign the second element's value to b, and then we use the **spread operator** (...) to say we want the rest of the elements in the array thereafter. You need to suffix the **spread operator** (...) with the name you'd like to give the rest of the array. Above we've simply called it **'restOfTheElements'**.

### Now, What does this look like?
```javascript
console.log(b);
console.log(restOfTheElements);
```
Would return:
```javascript
B
['C', 'D', 'E', 'F']
```

---

# Combining 2 Arrays <a name="combining-2-arrays-anchor">

You can also use the spread operator to combine 2 arrays together per the below example:

```javascript
const combinedArray = [...alphabet, ...numbers]
console.log(combinedArray);
```
This would return:
```javascript
['A', 'B', 'C', 'D', 'E', 'F', 1, 2, 3, 4, 5, 6]
```
Granted this isn't the most useful feature when it comes to arrays, given you could achieve the same with:
```javascript
const combinedArray = alphabet.concat(numbers)
```
However, this will come in handy when we touch on combining 2 or more objects together later on.

---

# Destructuring with Functions <a name="destructuring-with-functions-anchor">

Lets take the below example:
```javascript
function addAndMultiply(a, b) {
    return [a+b, a*b];
}

const array = addAndMultiply(4, 2);

console.log(array) //returns [6, 8]
```
We can apply array destructuring here per below: 
```javascript
function addAndMultiply(a, b) {
    return [a+b, a*b];
}

const [sum, multiply] = addAndMultiply(4, 2);

console.log(sum) //returns 6
console.log(multiply) //returns 8
```

What we're saying here is that we are destructuring the return from **addAndMultiply(4, 2)** as two different variables - one called sum, and one called multiply. Again, we destructure with **[ ]** because the return of **addAndMultiply(4, 2)** is an array, and we destructure into variables 'sum' and 'multiply' in that order, because that is the order that are returned in within the **'addAndMultiply'** function.

---

# Destructuring with Default Values <a name="destructuring-with-default-values-anchor">

We can also take the previous example and demonstrate destructuring with default values. For example:

```javascript
function addAndMultiply(a, b) {
    return [a+b, a*b];
}

const [sum, multiply, subtract = 'Subtraction Default'] = addAndMultiply(4, 2);

console.log(sum) //returns 6
console.log(multiply) //returns 8
console.log(subtract) // returns 'Subtraction Default'
```

---

# Object Destructuring <a name="object-destructuring-anchor">
_The true power of destructuring in Javascript_

Take the two simply objects below, **personOne** and **personTwo**:

```javascript
const personOne = {
    name: 'Naruto',
    age: 29,
    address: {
        city: 'Tokyo'
        country: 'Japan'
    }
}

const personTwo = {
    name: 'Sasuke',
    age: 28,
    address: {
        city: 'Osaka'
        country: 'Japan'
    }
}
```
If we want to get the name and age of personOne, we can use destructuring as follows:

```javascript
const { name, age } = personOne
 
 console.log(name); //returns 'Naruto'
 console.log(age); //returns 29
```
Note that we wrap name and age in curly braces **{ }** because we are destructuring an object.

And unlike array destructuring, which grabs elements in the array in sequential order, object destructuring matches by the key. I.e. name had to match name in the **personOne** object.


You can however rename the variable that you're destructuring if you so desire.

For example, we can destructure name from the object, but call it **firstName** instead as follows:
```javascript
const { name: firstName, age } = personOne
 
console.log(firstName); //returns 'Naruto'
console.log(name); //returns nothing as we remapped the var
```

## Defaults
We can also still use defaults in object destructuring. Lets take personTwo for example:

```javascript
const personTwo = {
    name: 'Sasuke',
    age: 28,
    address: {
        city: 'Osaka'
        country: 'Japan'
    }
}

const { name: firstName, age, job = 'Shinobi' } = personTwo

console.log(firstName); //returns 'Sasuke'
console.log(age); //returns 28
console.log(job); //returns 'Shinobi'
```

Above we can see we've added a property called job to the destructuring, and although it doesn't exist in the **personTwo** object, it has a default value set so it does return the value.

Similarly, if we added job to the object, it's default value would be overridden as follows:

```javascript
const personTwo = {
    name: 'Sasuke',
    age: 28,
    job: 'ninja',
    address: {
        city: 'Osaka'
        country: 'Japan'
    }
}

const { name: firstName, age, job = 'Shinobi' } = personTwo

console.log(firstName); //returns 'Sasuke'
console.log(age); //returns 28
console.log(job); //returns 'ninja'
```

You can even add defaults to renamed object variables too, per the below example:

```javascript
const personTwo = {
    name: 'Sasuke',
    age: 28,
    job: 'ninja',
    address: {
        city: 'Osaka'
        country: 'Japan'
    }
}

const { name: firstName = 'Tony', age, job = 'Shinobi' } = personTwo

console.log(firstName); //returns 'Sasuke'
```
As you can see above, we have name remapped to firstName, and have then also given it a default value of 'Tony'. Meaning if the name property did not exist within the personTwo object, then console.log(firstName) would return the default 'Tony'.

---

# Spreading

We can also use the spread operator here (just like we did with array destructuring) in order to get back the rest of the object. For example:

```javascript
const personTwo = {
    name: 'Sasuke',
    age: 28,
    job: 'ninja',
    address: {
        city: 'Osaka'
        country: 'Japan'
    }
}

const { name: firstName = 'Tony', age, ...rest } = personTwo

console.log(firstName); //returns 'Sasuke'
console.log(age); //returns 28

console.log(rest); 
//returns { job: "ninja", address: {city: "Osaka", country: "Japan"}}
```
As you can see, we've spread the rest of the object after destructuring the age, and we've mapped it to a variable called 'rest'. So when we log 'rest', we get the remainder of the object.

---

# Destructuring Nested Objects

We can also destructure nested objects.
Let's say we want to get only the city from personTwo. We can do this as follows:

```javascript
const personTwo = {
    name: 'Sasuke',
    age: 28,
    job: 'ninja',
    address: {
        city: 'Osaka'
        country: 'Japan'
    }
}

const { name: firstName = 'Tony', address: { city } } = personTwo

console.log(city); //returns 'Osaka'
```

---

# Combining Objects

We can also use destructuring to combine objects.

Below, we will create a personThree using parts of **personOne** and **personTwo**. 

Note that **personTwo** has been shortened to just **age** and **job** for the purposes of this example.

```javascript
const personOne = {
    name: 'Naruto',
    age: 29,
    address: {
        city: 'Tokyo'
        country: 'Japan'
    }
}

const personTwo = {
    age: 28,
    job: 'ninja',
}

const personThree = {...personOne, ...personTwo}
```

- Take everything inside **personOne** ---> put it in an object called **personThree**
- Take everything inside **personTwo** --> also put it in the same **personThree** object, but overwrite anything that was already in **personOne**.

**What does this give you?**

```javascript
console.log(personThree); 

//returns
const personThree = {
    name: 'Naruto',
    age: 28,
    job: 'ninja',
    address: {
        city: 'Tokyo'
        country: 'Japan'
    }
}
```

As you can see, the result of **personThree** is a spread **personOne**, overridden with anything that was in **personTwo** when it was spread into the same object thereafter.

---

# Object Destructuring Inside Function Arguments

Object destructuring inside of function arguments can be a powerful tool when it comes to code simplicity.

Take the below example which demonstrates passing **personOne** into a **printPerson** function, and printing some text that grabs particular attributes from the object, such as **name** and **age** in this example:

```javascript
const personOne = {
    name: 'Naruto',
    age: 29,
    address: {
        city: 'Tokyo'
        country: 'Japan'
    }
}

const printPerson = (person) => {
    console.log('Name: ${person.name}. Age: ${person.age}.);
}

printPerson(personOne);
//returns
"Name: Naruto. Age: 29"
```

If we used object destructuring within the function argument, we could avoid having to repeatedly prefix the attributes we want to pluck out with **person**.

Using object destructuring, we can rewrite the function as follows:

```javascript
const printPerson = ({ name, age }) => {
    console.log('Name: ${name}. Age: ${age}.);
}

printPerson(personOne);
//returns
"Name: Naruto. Age: 29"
```

As you can see, the above returns the exact same output. 

**What's happening exactly?**

Well, as you can see we're passing in **personOne** to **printPerson** when we call the function. And in the argument of the **printPerson** function we're destructuring **personOne** saying all we want is the **name** and the **age**.

We can also add defaults to the destructured arguments as follows:

```javascript
const personOne = {
    name: 'Naruto',
    age: 29,
    address: {
        city: 'Tokyo'
        country: 'Japan'
    }
}

const printPerson = ({ name, age, favouriteFood = 'Ramen'}) => {
    console.log('Name: ${name}. Age: ${age}. Favourite Food: ${favouriteFood}.);
}

printPerson(personOne);
//returns
"Name: Naruto. Age: 29. Favourite Food: Ramen."
```
Above you can see we've added a default for **favouriteFood** which currently does not exist in **personOne** so is being used. But if we added it to personOne then it would not use the default we've specified per below:

```javascript
const personOne = {
    name: 'Naruto',
    age: 29,
    favouriteFood: 'Takoyaki'
    address: {
        city: 'Tokyo'
        country: 'Japan'
    }
}

const printPerson = ({ name, age, favouriteFood = 'Ramen'}) => {
    console.log('Name: ${name}. Age: ${age}. Favourite Food: ${favouriteFood}.);
}

printPerson(personOne);
//returns
"Name: Naruto. Age: 29. Favourite Food: Takoyaki."
```

This is arguable the single most useful section of object destructuring - specifically when using it in React projects where you'll find object destructuring is heavily used in function calls.

Thanks for sticking through to the end! :)