DEV Community

Cover image for JavaScript Destructuring | All you need to know
Midas/XIV
Midas/XIV

Posted on • Edited on

JavaScript Destructuring | All you need to know

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:

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" }
Enter fullscreen mode Exit fullscreen mode

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

(() => {
    "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

})();
Enter fullscreen mode Exit fullscreen mode

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:

[pikachu, pidgey, charizard] = pokemonTypes;
Enter fullscreen mode Exit fullscreen mode

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 :

[pikachu, pidgey, ...hackedCharizard] = pokemonTypes;
Enter fullscreen mode Exit fullscreen mode

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.

[pikachu, , ...hackedCharizard] = pokemonTypes;
Enter fullscreen mode Exit fullscreen mode

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.

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'] 
Enter fullscreen mode Exit fullscreen mode

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.


2. Swapping two variables using Destructuring.

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
Enter fullscreen mode Exit fullscreen mode

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.


3. Basic Object Destructuring.

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}`);
Enter fullscreen mode Exit fullscreen mode

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.


4. Naming Variables & Nested Object Destructuring.

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}`);
Enter fullscreen mode Exit fullscreen mode

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.

let { name: MXIV } = pokemon;
console.log(`Name  :: ${MXIV}`);  // pikachu
Enter fullscreen mode Exit fullscreen mode

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:

let { ability: {
        primary: primaryAbility,
        hidden: hiddenAbility
    }
} = pokemon;

console.log(`ability   :: ${primaryAbility}`);  // Static
console.log(`ability   :: ${hiddenAbility}`);   // Lightning Rod
Enter fullscreen mode Exit fullscreen mode

5. Difference between Array and Object Destructuring.

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}`);
Enter fullscreen mode Exit fullscreen mode

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.

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); 
Enter fullscreen mode Exit fullscreen mode

6.- Filtering arguments to functions using Destructuring

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));
Enter fullscreen mode Exit fullscreen mode

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.


7. Filtering response from an API call using Destructuring.

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);
Enter fullscreen mode Exit fullscreen mode

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


8. For of iteration using Destructuring.

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();

}
Enter fullscreen mode Exit fullscreen mode

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.

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
Enter fullscreen mode Exit fullscreen mode

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.


Top comments (5)

Collapse
 
johncarroll profile image
John Carroll
// you need place the assignment in round brackets
({ prop1: name, prop2: location } = obj); 

^ Worth the read for that bit right there! I always wondered why I ran into issues with assignment using object destructuring.

Collapse
 
midasxiv profile image
Midas/XIV

Yeah, I tried to make it "the" article to refer to when looking up destructuring. And this small little piece is invaluable as I haven't seen it in other articles yet.

Collapse
 
monfernape profile image
Usman Khalil

Using Pokemon as example made it even more interesting

Collapse
 
midasxiv profile image
Midas/XIV

Thanks buddy 😌.

Collapse
 
midasxiv profile image
Midas/XIV

I personally have never found any use of it in my codebase. But it's definitely cool to use for logging API responses.