Demystifying Modern Destructuring in Javascript!

Demystifying Modern Destructuring in Javascript!

ยท

0 min read

bang.gif ...why does destructuring have to be hard?

The release of ES6 came with a host of really awesome features that changed the way we write code in Javascript such as the rest/spread operator, let and const, template literals, arrow functions, destructuring, classes etc. From that moment onward, it became every developer's goal to harness the power of these features to improve and simplify the programs we write. In this article, we'll be talking about the destructuring assignment.

The destructuring assignment syntax is a JavaScript expression that makes it possible to unpack values from arrays, or properties from objects, into distinct variables.

Simply put, destructuring makes it easier for us to assign values from an array/properties from an object to variables at once and be used anywhere in our program. One might wonder, why should this interest me? Let's consider a popular use case that shows why destructuring is indeed a welcome and much needed companion for every developer, especially considering the fact that we often find ourselves in this situation.

Imagine we have a page that displays the details of a certain developer. We have below a code snippet of how we usually handle this scenario before ES6 if the data structure is an object...

// data structure as an object
const developer = {
    name: 'John Doe',
    level: 'Senior',
    stacks: {
        html: 9,
        css: 8.5,
        javascript: 7
    }
};

const displayDetail = data => {
    const name = data.name;
    const level = data.level;
    const htmlRating = data.stacks.html;
    const cssRating = data.stacks.css;
    const javascriptRating = data.stacks.javascript;
    // Here we're using ES6 template literals
    console.log(`Hello ${name}, you're a ${level} level developer with a ${htmlRating}/10 proficiency in HTML, ${cssRating}/10 proficiency in CSS, and  ${javascriptRating}/10 proficiency in Javascript!`);
};

// function call
displayDetail(developer); 

//Output: Hello John Doe, you're a Senior level developer with a 9/10 proficiency in HTML, 8.5/10 proficiency in CSS, and  7/10 proficiency in Javascript!

And below is a code snippet for a scenario where the data structure is an array...

// data structure as an array
const stacks = ['HTML', 'CSS', 'Javascript'];

const displayDetail = data => {
    const html = data[0];
    const css = data[1];
    const javascript = data[2];
    // Here we're using ES6 template literals
    console.log(`Hello your stacks are ${html}, ${css} and ${javascript}`);
};

// function call
displayDetail(stacks); 

// Output: Hello your stacks are HTML, CSS and Javascript

Whew, that was a lot of code eh! From the snippets above it is clear that when we want to extract data from the array/object, we had to do the same thing over and over again. Now imagine we have quite a big application, this could get really cumbersome, tedious and repetitive.

drums rolls... enters the ES6 destucturing assignment, here to serve you better!

So let's take a look at how we would handle the above scenarios the ES6 way, first we'll talk about object destructuring then move to array destructuring and see tips to help get the best out of using the destructuring assignment in our projects going forward.

OBJECT DESTRUCTURING

This involves unpacking the properties in an object and assigning them to individual variables. We use an object literal on the left-hand-side of an assignment expression for object destructuring. Let's see how we can use the object destructuring syntax to assign values of an object to variables firstName, lastName, stack and country using the corresponding keys on the object.

const developer = {
  firstname: 'Abel',
  lastname: 'Agoi',
  stack: 'MERN',
  country: 'Nigeria'
};

// Object Destructuring
const { firstname, lastname, stack, country } = developer;

console.log(firstname, lastname, stack, country); // Abel Agoi MERN Nigeria

The above snippet shows us the most basic form of object destructuring, nonetheless there are several other use cases we could use the same syntax above to make our code cleaner and more readable. Let's consider a few examples:

New/Different Variable Names

When destructuring objects, it is normal practice to assign object values to variables who bear the same name as the corresponding key in that object but there are instances where we intend to store a value from an object in a variable named differently to the value's object key. Destructuring handles this case for us out of the box easily. Consider the snippet below:

const location = {
  city: 'Accra',
  country: 'Ghana',
  continent: 'Africa'
};

const { city: myHood, country: myPlace, continent: myZone } = location;

console.log(`I am proudly from ${myHood} ${myPlace} ${myZone}`);

// I am proudly from Accra Ghana Africa

From the example above, we can see it is possible to create local variables and map them to the respective object property/key we want it's value saved.

Default Values

Oftentimes we tend to know the object keys contained in an object before using a particular key in accessing the value. But what if we try accessing a non-existing key in a destructured object? Yes you guessed it, we're bound to get an 'undefined' returned. Default values can be assigned to a variable so that in the event that key doesn't exist on the destructured object, the assigned default value is returned. Below is a simple example:

const user = {
    name: 'Adu Samuel',
    country: 'Germany'
};

// CASE A: No default values assigned, hence undefined
const { name, country, club, age } = user;

console.log(`I am ${name} from ${country}, I am ${age} years old and I love ${club}.`);

// I am Adu Samuel from Germany, I am undefined years old and I love undefined.'

// CASE B: Assign default values of 'arsenal' to club and 49 to age
const { name, country, club = 'arsenal', age = 49  } = user;

console.log(`I am ${name} from ${country}, I am ${age} years old and I love ${club}.`);

// I am Adu Samuel from Germany, I am 49 years old and I love arsenal.'

We assigned default values to the club and age variables. Since they don't originally exist on the user object, 'arsenal' and 25 is assigned to the club and age variables respectively instead of undefined.

It is important to note that "a property can be both 1) unpacked from an object and assigned to a variable with a different name and 2) assigned a default value in case the unpacked value is undefined."

The above quote culled from the MDN Docs further shows we can have a combined layer of the two use cases stated earlier whenever we're working with object destructuring namely: setting new variables and setting default values for destructured objects in one go. A quick example below:

const employer =  {
    name: 'Mike Smith',
    family: {
      mother: 'Jane Smith',
      father: 'Harry Smith',
      sister: 'Samantha Smith'
    },
    age: 35
  };

const { name : fullName = 'Kuti Stark', maritalStatus : status = 'single' } = employer;

console.log(fullName); // Mike Smith
console.log(status); // single

Accessing Nested Object Values

Remember our very first code snippet? Yes, it contains what we call a nested object i.e an object that contains an object/an object of objects. Our 'stacks' object was nested in our 'developer' object. So what if we want to assign the developer's CSS and Javascript ratings to local variables, how do we use nested object destructuring to achieve this you might wonder? Let's see an example:

const developer = {
    fullName: 'John Doe',
    level: 'Senior',
    stacks: {
        html: 9,
        css: 8.5,
        javascript: 7
    }
};

const { fullName, stacks: { css: myCss, javascript: myJs } } = developer;

console.log(`I am ${fullName}, my CSS is ${myCss}/10 and my Javascript is ${myJs}/10`);

// I am John Doe, my CSS is 8.5/10 and my Javascript is 7/10

Here, we created three variables. fullName which was defined also in the developer object, and we used nested object destructuring to pull out css and javascript values from the nested stacks objects then store them in the myCss and myJs variables respectively.

Object Destructuring with Rest

Another awesome feature that came with the ES6 release, the rest operator can be used seamlessly with object destructuring. The use case for this is when only one or two keys in an object is destructured into a variable(s) and every other remaining keys are unpacked into a single variable. What this means is that the rest property(can be named anything) collect the remaining own enumerable property keys that are not already picked off by the destructuring pattern. Let's see a simple example:

const userDetail = {
        name: 'Segun Omilabu',
        email: 'patient@eyeshop.com',
        dueDate: '3-4 Days',
        _id: 2,
        phone: '08012345622'
        service: ['radiology', 'chemotherapy']
};

const { name, email, ...otherDetails  } = userDetail;

console.log(name);   // Segun Omilabu
console.log(email);   // patient@eyeshop.com
console.log(otherDetails);   // {
//        dueDate: '3-4 Days',
//        _id: 2,
//        phone: '08012345622',
//        service: ['radiology', 'chemotherapy']
// }

These are some of the use cases you'll find yourself when trying to destructure objects in your program. Putting all we've learned in this article so far together, let's rewrite that very first code snippet the ES6 object destructuring way.

// data representation as an object
const developer = {
  name: 'John Doe',
  level: 'Senior',
  stacks: {
      html: 9,
      css: 8.5,
      javascript: 7
  }
};
// ES6 object destructuring
const displayDetail = data => {
    const { name, level, stacks: { html: htmlRating, css: cssRating, javascript: javascriptRating } } = data;
    console.log(`Hello ${name}, you're a ${level} level developer with a ${htmlRating}/10 proficiency in HTML, ${cssRating}/10 proficiency in CSS, and  ${javascriptRating}/10 proficiency in Javascript!`);
};

// function call
displayDetail(developer); 

//Output: Hello John Doe, you're a Senior level developer with a 9/10 proficiency in HTML, 8.5/10 proficiency in CSS, and  7/10 proficiency in Javascript!

ARRAY DESCTRUCTURING

Fresh from our buzzing knowledge of object destructuring, we have an equally straightforward approach to unpacking values from an array. Although there are similarities, it is important to note that we use an array literal on the left-hand-side of an assignment expression in array destructuring and each declared variable name on the array literal maps to the corresponding item at the same index on the destructured array. Remember our first code snippet where we had to target individual array index in order to access a data from the array? Array destructuring helps us avoid going through that repetitive process. Let us consider an example to understand this:

const bioData = [
  'Bosco Kapaichumarimarichupako', 
  '08012345622', 
  'bosco@insidelife.com', 
  'Zion City Ltd'
];

// Array destructuring
const [name, phoneNumber, emailAddress, company] = bioData;

console.log(name); // Bosco Kapaichumarimarichupako
console.log(phoneNumber); // 08012345622
console.log(emailAddress); // bosco@insidelife.com
console.log(company); // Zion City Ltd

Here, we assigned the values in the array to local variables: name, phoneNumber, emailAddress, and company using the array destructuring syntax. You'd notice that variables are set from left to right which means the first variable gets the first item(at index 0) in the array, the second variable gets the second item(at index 1) in the array and so on. Hence, each variable is mapped to the corresponding item at the same index on the bioData array.

The code snippet we see above shows us the most basic form of array destructuring, but let's consider a few other use cases we could use the syntax above when working on destructured arrays in our programs...

Skipping Items in an Array

You might find yourself in situations where you only want to get the first, second and the fourth items in an array. How do you store these specific items into variables? With array destructuring, this can also be done. Look at the example below:

const bioData = [
  'Bosco Kapaichumarimarichupako', 
  '08012345622', 
  'bosco@insidelife.com', 
  'Zion City Ltd'
];

// Destructuring the first, second and fourth items from the array
const [name, phoneNumber, , company] = bioData;

console.log(name); // Bosco Kapaichumarimarichupako
console.log(phoneNumber); // 08012345622
console.log(company); // Zion City Ltd

Do you know what just happened? We took values from the array and store them in variables but skip the value we don't need by adding a comma separator "," at the index we're skipping. Easy right? Let's take one more example:

const bioData = [
  'Bosco Kapaichumarimarichupako', 
  '08012345622', 
  'bosco@insidelife.com', 
  'Zion City Ltd'
];

// Destructuring the first and fourth items from the array
const [name, , , company] = bioData;

console.log(name); // Bosco Kapaichumarimarichupako
console.log(company); // Zion City Ltd

Here, we even skipped two values from the array using the comma separator "," by storing only the first and last values into variables. Therefore, if you ever need to skip an item or items in an array, just use a comma.

Array Destructuring with Rest

This is one of a few similarities array and object destructuring have in common, basically we're using the rest operator to save any unpacked items in an array into a single variable after some of the array item(s) has been assigned to variable(s). How do we do this?

const bioData = [
  'Omolaw Bawo', 
  'Dallas Mavericks', 
  'Ogabashi', 
  '08012345678'
];

// Destructuring with the rest operator
const [name, , codeName, ...otherData] = bioData;

console.log(name); // Omolaw Bawo
console.log(codeName); // Ogabashi
console.log(otherData); // ['Dallas Mavericks', '08012345678']

From the code above, we assigned the first and third items to variables name and codeName respectively after which we used the rest operator syntax to assign the remaining items to the otherData variable.

*It is important to note that if you're using the rest operator while destructuring like the example above, it must always appear as the last item in the destructuring array literal otherwise an error will be thrown.

Default Values

This is another similarity array destructuring shares with object destructuring. We assign default values to the variables just in case the value extracted from a given array is undefined. That means even if a corresponding item in an array is not found, the default value we assign will be the output. Consider the example below:

const userInfo = ['Msimo Doh', 'Mayor of Makurdi'];

// Setting a default value
const [name, title, age = 75] = userInfo;

console.log(name); // Msimo Doh
console.log(title); // Mayor of Makurdi
console.log(age); // 75

As you can see, there's no third item on the userInfo array but in array destructuring we can set a default value so the age variable outputs 75 instead of undefined

Function Destructuring

What if you have a function in your program that returns an array and you'd like to destructure this array? If you're a React Developer, this is a use case you'll bump into when working with React hooks or when making your own custom hooks. Not to worry, with array destructuring you can extract the data from an array returned from a function. Let's see an example:

const showStudents = () => {
  return ['Hassan', 'Alloy', 'Johnson', 'Luiz'];
};

// Array destructuring a function
const [student1, student2] = showStudents();

console.log(student1, student2); // 'Hassan Alloy'

Accessing Nested Array Values

We've considered how to access nested object values. Likewise, with an array that contains nested array(s) we can also achieve nested destructuring. We do this by using nested destructuring array literal to assign corresponding items in the array to local variables. Let's consider a simple example:

const serviceData = [
  'Dentistry',
  ['Radiology', 'Chemo', 'Biology'],
  ['Optical', 'Clinical']
];

// Using nested array destructuring to assign variables
// const [dentist, [radiologist, , biologist], [optician]] = serviceData;

// console.log(dentist, radiologist, biologist, optician); 
// 'Dentistry' 'Radiology' 'Biology' 'Optical'

From the above code, we can see how we assigned the first item from the serviceData array to the dentist variable then used nested array destructuring to assign items to the radiologist, biologist and optician variables. We even used one of the nice array destructuring tools we learned earlier in this article, skipping an item in the first nested array in the serviceData array.

That's some of the many use cases you'll find yourself when trying to destructure arrays in javascript. Feels like you just acquired a superpower yeah? YES! So once again, let's rewrite that very first code snippet the ES6 array destructuring way.

// data representation as an array
const stacks = ['HTML', 'CSS', 'Javascript'];

// ES6 array destructuring
const displayDetail = data => {
    const [html, css, javascript] = data;
    console.log(`Hello your stacks are ${html}, ${css} and ${javascript}`);
};

// function call
displayDetail(stacks); 

// Output: Hello your stacks are HTML, CSS and Javascript

CONCLUSION

Yaaayy, Destructuring Superman! You made it to the concluding part of this tutorial, where we explored the ES6 destructuring syntax and several ways we can apply it in our code. I'm sure you'll agree with me that having a solid knowledge of ES6 destructuring saves us from writing extra repeated and unnecessary lines of code and saves time. Thanks for reading and Happy coding. Please feel free to leave a comment or question! Cheers ๐Ÿฅ‚