destructuring

In the current post, we will start with the code using ES5 syntax.

var expense = {
  type: "Business",
  amount: "50$"
};

Imagine we have a simple code like that somewhere in the project.

Now comes the time that later in our code we want to refer to our object and extract some data from it. We would probably do it this way. A simple dot notation allows us to get data from the object.

var expense = {
  type: "Business",
  amount: "50$"
};

var type = expense.type;
var amount = expense.amount;

Is this a good way? Of course. Could we do better? Since the ES6, there is a way. You've probably heard about DRY a lot, which means Don't Repeat Yourself. In the example above, as you can see it yourself, we repeat ourselves several times. Two vars, two expenses, two types, two amounts. This is a place where ES6 comes handy to let us simplify writing a bit.

var expense = {
  type: "Business",
  amount: "50$"
};

// ES5
var type = expense.type;
var amount = expense.amount;

//ES6
const { type } = expense;
const { amount } = expense;

What we wrote with ES6 is completely equal to what we used before. This way of writing means that from the expanse object, we want to extract type and amount then assign them to const variables with the same name. We must remember that we need to specify exactly what we want to refer to by using the same variable name.

But aren't there still any duplicates in the example above? Of course, there are. So let's modify our code even more.

var expense = {
  type: "Business",
  amount: "50$"
};

// ES5
var type = expense.type;
var amount = expense.amount;

//ES6
const { type, amount } = expense;

As you can see, we completely got rid of the duplicates. Let's check the console if everything works as it should.

Cool. If it works now, will it work if we change the name of the variable to another one that does not exist in the object?

var expense = {
  type: "Business",
  amount: "50$"
};

const { myType, myAmount } = expense;

Unfortunately, but no. The convention of this says clearly that the variable name has to be the same as it is in the object. But what if we really really what to use a different name of the variable? Well, there is also a solution for that but try to solve it yourself (a small hint, use a colon and the name of the new variable).

What else can we do using destructuring? For example, we can extract a parameter passed to a function. We will start as above from the script written using ES5.

var file = {
  name: 'dog',
  extension: 'jpg',
  size: 1100
};

function fileSummary(file) {
  return `The file ${file.name}.${file.extension} is ${file.size} GB big`;
}

Ok, hold on. And what is this notation ?! Here we are dealing with another feature from ES6, template strings.

template strings

For a moment we will leave destructuring to see what template strings are.

Template strings, or otherwise template literals, are nothing more than syntactic sugar in JavaScript. Here, we will also use two examples. The first one will be something you probably used to do using JavaScript.

function msg() {
  const year = new Date().getFullYear();

  return "The year is " + year;
}

We've all expected this. Once again, however, the question arises whether you can write it a little more elegantly. And the answer is once again that you can.

function msg() {
  const year = new Date().getFullYear();

  return `The year is ${year}`;
}

Everything works correctly. Additionally, we do not have to limit ourselves to the year variable. We can put any expression in { }. If we would like to receive a previous year, just change it to {year - 1}, etc. It is possible that it is not visible enough but we use backticks to write the template string. We can find them on the keyboard next to the number 1 (on the left). And that's all you need to know. It is not complicated, and I think that it will often help with the code readability.

destructuring

We are going back to the previous example.

var file = {
  name: 'dog',
  extension: 'jpg',
  size: 1100
};

function fileSummary(file) {
  return `The file ${file.name}.${file.extension} is ${file.size} GB big`;
}

If we know what the template strings are, we can go further. And what are we doing next? Of course, we try to use destructuring to make our code more beautiful.

var file = {
  name: 'dog',
  extension: 'jpg',
  size: 1100
};

function fileSummary( {name, extension, size} ) {
  return `The file ${name}.${extension} is ${size} GB big`;
}

fileSummary(file);

Once again everything works correctly. Instead of writing the name of the object every time we want to refer to one of its property. All you need to do is invoke the function with an argument, which will be the object. In the function, we will pass the properties to which we want to refer in the body.

Everything is beautiful and nice but shortening the code is not the only thing for which destructuring is used. Often destructuring of an array is also used. When we were destructuring objects, we were pulling off properties. Destructuring arrays is about pulling off individual elements.

const companies = [
  "Google",
  "Apple",
  "Facebook"
];

const [ name1, name2, name3 ] = companies;
console.log(name1, name2, name3);

// es5
var firstCompany = companies[0];
console.log(firstCompany);

Here is another way to use destructuring. The difference between destructuring of an array and an object is that { } has been replaced by [ ]. I am encouraging everyone to play around with it a bit now. After that, we will take a look at the destructuring the mix of arrays and objects.

const companies = [
  { name: "Google", location: "USA" },
  { name: "Facebook", location: "USA" },
  { name: "2N IT", location: "Poland"}
];

const [ firstElementOfArray ] = companies;
console.log(firstElementOfArray);

const [ {name} ] = companies;
console.log(name);

In the example above, we have an array with 3 objects. We know that using destructuring we can extract data from both, first and second. Now let's see how it is done.

Of course, we start with the array, as it is "outside" our objects. firstElementOfArray will be our first object and in the first console.log. Of course, we will get the whole object back. If we add to this { } and change the name firstElementOfArray to the name of the one object's property, in our case name, we will get its value. Simple right? If we would like to gain access to the name but the other company, we would do it in the following way.

const companies = [
  { name: "Google", location: "USA" },
  { name: "Facebook", location: "USA" },
  { name: "2N IT", location: "Poland"}
];

const [ firstCompany, { name } ] = companies;
console.log(name);

Now let's reverse the situation and create an array inside an object.

const Google = {
  locations: ["USA", "Poland", "Germany"],
};

const { locations: [ locationOne ] } = Google;
console.log(locationOne);

It probably looks a little more confusing, but it is not that complicated. Let's start from the beginning. In the beginning, as the object is "outside", we start with { }. Now, to get to the location property, we have to type the variable exactly with the same name, i.e. location { location }. Leaving it this way, we would get all the values, i.e. ["USA", "Poland", "Germany"]. However, when our goal is to obtain only "USA" we must use destructuring once again, { locations: [ locationOne ] }. This way, we'll gain access to the first location of Google. Here I also encourage you to play ... rest.

In the nex post, I'll be talking about asynchronous javascript.