Destructuring - One Use Case

I've written previously about some of my favorite features of ES2015 (formerly known as ES6). If you have read those, you probably know that I really like string interpolation, block-scoped variables, and context-preserving arrow functions. But one feature which I have not used until now is object and array destructuring.

Destructuring is a very concise and readable way to extract parts of arrays or objects. It is not necessary all the time, but sometimes it can make you code cleaner and more readable.

Destructuring Objects

Traditionally in JavaScript, if you wanted to extract values from an object you would do something like this:

// first, we have an object whose data we want to extract

var myObj = {
  name: 'Ryan',
  age: '30',
  color: 'green'
};

// next, we extract the values one by one

var n = myObj.name;
var a = myObj.age;
var c = myObj.color;

// we can now do whatever we need to do with those variables

console.log(n, a, c);

Now, obviously, we don't always need to extract values into their own variables. But if you need to manipulate those values in some way, you generally will extract them rather than writing myObj.something over and over again. In this case, please assume there is a reason that we need to extract the values into their own variables.

Destructuring allows us to accomplish the same thing, just in a more concise manner.

let myObj = {
  name: 'Ryan',
  age: '30',
  color: 'green'
};

// next, we extract the values at once using destructuring

let {name: n, age: a, color: c} = myObj;

// we can now do whatever we need to do with those variables

console.log(n, a, c);

There you go! We got the values out like before, but this time we did it using destructuring rather than individually extracting them.

Destructuring Arrays

If you understand destructuring Objects, then you can probably already guess how destructuring arrays works.

Traditionally, you would do this:

// first, we have an array whose data we want to extract

var myArr = [
  'value1',
  'value2',
  'value3'
];

// next, we extract the values one by one

var first = myArr[0];
var second = myArr[1];
var third = myArr[2];

// we can now do whatever we need to do with those variables

console.log(first, second, third);

Using destructuring, we can extract the values like this:

// first, we have an array whose data we want to extract

let myArr = [
  'value1',
  'value2',
  'value3'
];

// next, we extract the values at once using destructuring

let [first, second, third] = myArr;

// we can now do whatever we need to do with those variables

console.log(first, second, third);

So, as you can see, we declared our variables inside square brackets and it extracted the first item in the array into the first variable, the second into the next variable, and so on. Order matters when destructuring arrays!

One Use Case

As I said earlier, I knew about variable assignment using destructuring, but I have not until now really found a use case where it made a lot of sense to use, especially for destructuring arrays. But with the project I am currently working on, I am pulling data from the Facebook Page Graph API.

Using the API, I can make calls to Facebook and get an object back with a page's public data. I am using it to get information about businesses. It sends back a JavaScript object with the requested data. A response might look like this (depending on which fields you requested).

let demonstratedResponse = {
  name: 'My Business Name',
  about: 'We are a business... isn't that exciting!',
  phone: '(123) 456-7890'
  hours: {
    fri_1_open: '8:00',
    fri_1_close: '12:00',
    fri_2_open: '13:00',
    fri_2_close: '18:00',
    sat_1_open: '8:00',
    sat_1_close: '17:00'
  }
};

I could use object destructuring if I wanted to here, but I really don't need to extract multiple value into their own variables, so it's not worth my time to bother. But notice those hours. Facebook has stored information for each day's hours in each key in the hours object (e.g. fri_1_open). Facebook allows two different time ranges per day, in this case it looks like the business takes an hour off at lunch time on Fridays.

Looking at each key, we see what the day is, the hours range (whether 1 or 2), and the type (open or close). I don't want to store the hours in my data object like that. I want to extract those values into objects which I can then read. I want my hours data to look like this:

let hours = {
  fri: {
    open1: '8:00',
    close1: '12:00'
  },
  // and so on
}
This is a perfect use case for destructuring!

Traditionally, I would get the data like this:

// this is my simulated response from Facebook

var demonstratedResponse = {
  name: 'My Business Name',
  about: 'We are a business... isn\'t that exciting!',
  phone: '(123) 456-7890',
  hours: {
    fri_1_open: '8:00',
    fri_1_close: '12:00',
    fri_2_open: '13:00',
    fri_2_close: '18:00',
    sat_1_open: '8:00',
    sat_1_close: '17:00'
  }
};

// this is my default hours object which I want to populate w/ data from Facebook

var myHours = {
  sun: {},
  mon: {},
  tue: {},
  wed: {},
  thu: {},
  fri: {},
  sat: {}
};

var fbHours = demonstratedResponse.hours;

var keys = Object.keys(fbHours);

// define variables which I'll be using in the for loop

var splitKey, day, num, time;

// loop through each key in the hours object from FB

for (var i = 0; i < keys.length; i++) {

  // first, I split the key into an array

  splitKey = keys[i].split('_');

  // next, I extract the values

  day = splitKey[0];
  num = splitKey[1];
  type = splitKey[2];

  // then, I add them to my object

  myHours[day][type + num] = fbHours[keys[i]];
}

console.log(myHours);

View at JSFiddle

The Facebook API guarantees me (at least in the current version) that I can always expect my hours data to look like this. That's why I can safely grab the first three values from the array and know what they are (day, type, etc.). But now I am going to write this using ES2015 and array destructuring.

// this is my simulated response from Facebook

const demonstratedResponse = {
  name: 'My Business Name',
  about: 'We are a business... isn\'t that exciting!',
  phone: '(123) 456-7890',
  hours: {
    fri_1_open: '8:00',
    fri_1_close: '12:00',
    fri_2_open: '13:00',
    fri_2_close: '18:00',
    sat_1_open: '8:00',
    sat_1_close: '17:00'
  }
};

// this is my default hours object which I want to populate w/ data from Facebook

let myHours = {
  sun: {},
  mon: {},
  tue: {},
  wed: {},
  thu: {},
  fri: {},
  sat: {}
};

let fbHours = demonstratedResponse.hours;

// loop through each key in the hours object from FB
// I am using 'let' so the variables are block-scoped
// and don't need to be declared outside of the loop

for(let key of Object.keys(fbHours)) {

  // first, I split the key into an array
  
  let splitKey = key.split('_');
  
  // next, I extract the values using destructuring
  
  let [day, num, type] = splitKey;
  
  // then, I add them to my object
  myHours[day][type + num] = fbHours[key];
  
}

console.log(myHours);

View at JSFiddle

Using ES2015 in general allows me to write this in a more clean and concise way. But notice in particular the line: let [day, num, type] = splitKey;. That is very straightforward and allows you to extract those values without the repetition necessary when extracting them individually. In this case, I always know what indexes 0, 1, and 2 are going to be in the split array, so this is a beautiful use case for destructuring.

Conclusion

So, in conclusion, use destructuring! Or do not use destructuring. It is up to you. I find that my code is much more concise and readable using ES2015 in general, and using destructuring for use cases like above. But, let me warn you, many features of ES2015 are still not natively supported in browsers and in Node. In my current case, I am building an application using the Meteor framework, which automatically transpiles my code from ES2015 to ES5 so it is compatible with nearly all browsers. But if you are not using a framework which does all that work automatically for you, you will need to use a transpiler like Babel.

But, while ES2015 is not natively run everywhere, the fact of the matter is that it is the future. So, you might as well get comfortable using the new syntax now!