JavaScript Destructuring | All you need to know
Tags: javascript, node, webdev, beginners
Published: 2019-10-13 20:27:49

Hey guys, so I've been continuing to look into ES6 features and just absolutely essentials things to know in JavaScript, like IIFE, "use strict", closures, hoisting, etc and I keep avoiding a certain topic as it straight up looks intimidating and confusing, for example:

```javascript
var pokemon =  {
    id: 25,
    name: 'Pikachu',
    type: ['electric'],
    ability: {
      primary: 'Static',
      hidden: 'Lightning Rod'
    },
    moves: ['Quick Attack', 'Thunderbolt', 'Iron Tail', 'Volt Tackle'],
    competative: [
      { weakness: ['Ground'] },
      { resistance: ['Flying', 'Steel', 'Electric'] }
    ]
  };

var returnMoves = function({moves}){
  return moves;
}

var returnAbilities = function({ability}){
  return ability;
}

console.log(returnMoves(pokemon));
// ["Quick Attack", "Thunderbolt", "Iron Tail", "Volt Tackle"]
console.log(returnAbilities(pokemon));
// { hidden: "Lightning Rod", primary: "Static" }
```

as you can see we're passing the same object (pokemon) argument to two different functions and we get completely different outputs. 

So let's get started; "Destructuring is a JavaScript expression that makes it possible to unpack values from arrays, or properties from objects, into distinct variables"-MDN, so let's start with a few basic example.

> Lot of code ahead !

## 1. Basic Array Destructuring

```javascript
(() => {
    "use strict";
    let pokemonTypes = ['electric', 'flying', 'fire', 'grass'];
    let pikachu, pidgey, charizard, venusaur;

    // pikachu   = pokemonTypes[0];
    // pidgey    = pokemonTypes[1];
    // charizard = pokemonTypes[2];

    // Skipping Values and default values.
    [pikachu, , charizard, venusaur = 'NONE'] = pokemonTypes;

    console.log(`Pikachu   - ${pikachu}`);     // electric
    console.log(`Pidgey    - ${pidgey}`);      // undefined
    console.log(`Charizard - ${charizard}`);   // fire
    console.log(`Venusaur  - ${venusaur}`);    // grass

})();
```

So we'll start with array destructuring, so let's say we need to get the values of the array into individual variables the simplest way to do this is write `variable = Array[index]` but when we have multiple assignments it can make the code slightly verbose.
So to destructre the array we first declare variables in our case `pikachu,pidgey,charizard` then we simply write these variables within box brackets and assign it the whole array like so:

```javascript
[pikachu, pidgey, charizard] = pokemonTypes;
```

as you'll notice we have 4 array members but only 3 variables, does that mean charizard gets the last two values ? fire and grass. ( being a pokemon fan this would be kinda sick especially if it had levitate or something ) but that is not the case, charizard only receives the corresponding member which fire. So to receive the "rest" of the members the destructuring assignment has something called the "Rest element", it is as follows : 
```javascript
[pikachu, pidgey, ...hackedCharizard] = pokemonTypes;
```

So now **hackedCharizard** becomes the rest element which means it recieves the rest of the elements after the second member of the array giving it value fire and grass. the rest element must be the last element, if it is not you'll get an error.

Now let's say we wish to skip one of the members of the array we can do this by simply skipping the variable in it's place as follows.
```javascript
[pikachu, , ...hackedCharizard] = pokemonTypes;
```
So we skipped pidgey, if we checkout the value of pidgey it would give us undefined. we can also give our variables default values in case the array doesn't have a member corresponding to it.
```javascript
let pokemonTypes = ['electric', 'flying', 'fire'];
[pikachu, pidgey , charizard, venusaur = 'NONE'] = pokemonTypes;
//['electric','flying','fire','NONE'] 

pokemonTypes = ['electric', 'flying', 'fire','grass'];
[pikachu, pidgey , charizard, venusaur = 'NONE'] = pokemonTypes;
//['electric','flying','fire','grass'] 
```
But when we have an array member to assign it a value, it overrides our default value.

> I think that's all there is to array destructuring, if I missed anything let me know, I'll gladly update.

<hr>

## 2. Swapping two variables using Destructuring.

```javascript
let a = 34, b = 89;

console.log(`OLD - a :: ${a} | b :: ${b}`);  // OLD - a :: 34 | b :: 89`

// Swap two variables
// let temp = a;
// a = b;
// b = temp;

// Destructuring assignment

[a,b] = [b,a];

console.log(`NEW - a :: ${a} | b :: ${b}`); // NEW - a :: 89 | b :: 34
```

So another cool use of destructuring is to swap variable values, we simply write the variables in box bracket on the LHS and write the variables we want in order you require in RHS. 
This can also be done with 3 variables or any number.

<hr>

## 3. Basic Object Destructuring.
```javascript
let pokemon = {
    "name": "Pikachu",
    "id": 25,
    "type": "electric",
};
let { type, name, moves } = pokemon;

console.log(`Name      :: ${name}`);
console.log(`Type      :: ${type}`);
console.log(`moves     :: ${moves}`);
```
When destructuring an object we write the variables in curly bracket instead of the box bracket, also notice how we can write the variables in any order this is because the variable name is the exact same as the property of the object. Checkout the next section for some advanced usage.

<hr>

## 4. Naming Variables & Nested Object Destructuring. 
```javascript
let pokemon = {
    "name": "Pikachu",
    "id": 25,
    "type": "electric",
    "ability": {
        "primary": "Static",
        "hidden": "Lightning rod"
    },
    "moves": ["Quick Attack", "Volt Tackle", "Iron Tail", "Thunderbolt"]
};
let {
    type,
    name: MXIV,
    moves,
    ability: {
        primary: primaryAbility,
        hidden: hiddenAbility
    },
    moves: [firstMove, , lastMove]
} = pokemon;

console.log(`Name      :: ${MXIV}`);
console.log(`Type      :: ${type}`);
console.log(`moves     :: ${moves}`);
console.log(`ability   :: ${primaryAbility}`);
console.log(`ability   :: ${hiddenAbility}`);
console.log(`1st Move  :: ${firstMove}`);
console.log(`last Move :: ${lastMove}`);
```
In this section we'll mainly try to rename the variable and also do nested destructuring. To do this we must write the variable name then the custom variable like so.

```js
let { name: MXIV } = pokemon;
console.log(`Name  :: ${MXIV}`);  // pikachu
```
when you rename the variable we can no longer use the original variable in our case we can no longer use "name" but only "MXIV".

Next let's try to destructure nested properties, to do this we must write the property then colin then curly brackets and then the nested property name, to give this a custom variable name we simply write the property name then colin and finally the custom variable name, like so:
```js
let { ability: {
        primary: primaryAbility,
        hidden: hiddenAbility
    }
} = pokemon;

console.log(`ability   :: ${primaryAbility}`);  // Static
console.log(`ability   :: ${hiddenAbility}`);   // Lightning Rod
```
<hr>

## 5. Difference between Array and Object Destructuring.
```javascript
let arr = [10, 20];
let one, two;
[one, two] = arr;

console.log(`${one} ${two}`);

let obj = { prop1: 'mxiv', prop2: 'UAE' };

let name, location;
({ prop1: name, prop2: location } = obj);

console.log(`${name} ${location}`);
```
In case of array destructuring we can declare our variables without assigning them immediately, but when you try to do the same for objects, you wont be able to do the same.
```javascript
let obj = { prop1: 'mxiv', prop2: 'UAE' };

let name, location;
// { prop1: name, prop2: location } = obj //gives error

// you need place the assignment in round brackets
({ prop1: name, prop2: location } = obj); 
```

<hr>

## 6.- Filtering arguments to functions using Destructuring
```javascript
let pokemon = {
    "name": "Pikachu",
    "id": 25,
    "type": "electric",
    "ability": {
        "primary": "Static",
        "hidden": "Lightning rod"
    },
    "moves": [
        "Quick Attack", "Volt Tackle", "Iron Tail", "Thunderbolt"
    ],
    "competative": {
        "weakness": ["ground"],
        "strengths": ["water", "flying"],
        "resistances": ["electric", "flying", "water", "steel"]
    }
};

const getWeakness = ({competative:{weakness:isWeakTo}})=>{
    return isWeakTo;
};

const getStrengths = ({competative:{strengths:isStrongTo}})=>{
    return isStrongTo;
}

const getResistances = ({competative:{resistances:isResistantTo}})=>{
    return isResistantTo;
}

const getMoves = ({moves})=>{
    return moves;
}

const stat = ({name = 'NOT DEFINED' , competative:{weakness}})=>{
    return `${name} is weak to - ${weakness}`;
}

console.log(`Weakness    :: ${getWeakness(pokemon)}`);
console.log(`Strengths   :: ${getStrengths(pokemon)}`);
console.log(`Resistances :: ${getResistances(pokemon)}`);
console.log(`Moves       :: ${getMoves(pokemon)}`);

console.log(stat(pokemon));
```

This is self explanatory , the idea is that sometimes you just don't have all parameters to a function and instead of making the call by passing in empty parameters or null, it's better to use destructuring and assign a default value right in the argument definition. 

<hr>

## 7. Filtering response from an API call using Destructuring.
```javascript
let pokemon = {
    "name": "Pikachu",
    "id": 25,
    "type": "electric",
    "ability": {
        "primary": "Static",
        "hidden": "Lightning rod"
    },
    "moves": ["Quick Attack", "Volt Tackle", "Iron Tail", "Thunderbolt"]
};

const getAbilities = ({ability})=>{
    return ability;
}

let {primary:primaryAbility} = getAbilities(pokemon);
let {hidden:hiddenAbility} = getAbilities(pokemon);
console.log(primaryAbility);
console.log(hiddenAbility);
```

Once again one of the best usage of destructuring, I didn't want to make an API call but in the above example the getAbilities() function returns an object with hidden and primary ability. You can directly filter them instead of writing `response.property or response.property.nestedProperty`

<hr>

## 8. For of iteration using Destructuring.
```javascript
let pokemons = [{
    "name": "Pikachu",
    "id": 25,
    "type": "electric",
    "ability": {
        "primary": "Static",
        "hidden": "Lightning rod"
    },
    "moves": ["Quick Attack", "Volt Tackle", "Iron Tail", "Thunderbolt"]
}, {
    "name": "Charizard",
    "id": 6,
    "type": "fire",
    "ability": {
        "primary": "Blaze"
    },
    "moves": ["flame thrower"]
}];

for (let {name,type,moves,ability:{primary:primaryAbility}} of pokemons) {
    console.log(`${name} is type ${type}`);
    console.log(`has moves ${moves}`);
    console.log(`Primary Ability is :: ${primaryAbility}`);
    console.log();

}
```
So the main thing to know here is the difference between "for of" and "for in" when we use "for of" we get the value of the array member rather than the index.

```javascript
let arr = [10,20,304,50];
for( let i in arr) { console.log(i); } // 0 1 2 3
for( let i of arr) { console.log(i); } // 10 20 304 50
```

So in our case in place of "i" we have our destructuring assignment.

This is greatly inspired by a post I saw on Facebook on a page called `Coding with Daniel`; I would personally have never thought of using destructuring in such a way.

<hr>