Why are We Here?
It's dead simple. We are here to learn about an ECMAScript 6 (ES6) feature called Destructuring. You know ECMAScript 6 (ES6) right???
Well to keep it simple, ECMAScript is a scripting language specification. One of the major implementations of ECMAScript is JavaScript. ECMAScript 6, also known as ECMAScript 2015, is the latest version of the ECMAScript standard. Let's start leaning about one of its major features called "Destructuring" with a story in the next section.
The Magic Box Story
Let's imagine we have a Magic Box.
Our magic box has these features:
- You can put anything inside the magic box
- You can fill all your items at a time or you can fill whenever you want
- The magic box can answer your questions about its items.
Well who would not want a magic box like this right?
So let's put some stuff inside the magic box. Let us put:
- 3 books
- 5 toys
- A box of food which contains pizza, chocolate and ice cream
- A smaller magic box which contains 3 pens and a fruit box which has four fruit items in it (i.e.: apple, mango, banana and grape)
Let's visualize our magic box a bit.
Now that we have some items inside the magic box, let's ask it some questions. Suppose we have ten people who are asking a distinct question to the magic box. Let the questions be:
- How many books do you have?
- How many toys do you have?
- What is the first food item?
- What is the second food item?
- What is the third food item?
- How many pens do you have inside the small magic box?
- What is the first fruit item inside the small magic box?
- What is the second fruit item inside the small magic box?
- What is the third fruit item inside the small magic box?
- What is the fourth fruit item inside the small magic box?
The magic box says, "I can answer all your questions but only one at a time".
Well, it's fine, but what if it could give all answers at a time?
Do You Feel Bored? Come on! The article just started and you feel sleepy! :)
The reason I am boring you with this magic box story is, JavaScript object construction is very much flexible like the magic box. You can put anything you want like string, array, function, other objects, etc. you can create the object all at a time or can assign property any time you want. JavaScript's flexibility is well documented and widely known so let's not get into details of that. But what about extracting properties from object?! Well, until ECMAScript 6 (ES6) arrived, JavaScript had some limitations just like our magic box. To understand this, let us create our sample magic box object in JavaScript.
var magicBox = {
book: 2,
toy: 5,
foodBox: ['pizza', 'chocolate', 'ice cream'],
smallMagicbox: {
pen: 3,
fruits: ["apple","mango", "banana","grape"]
}
};
Now let's try to get the answers that we asked the magic box. In JavaScript, it will look something like this:
var book = magicBox.book;
var toy = magicBox.toy;
var firstFoodItem = magicBox.foodBox[0];
var secondFoodItem = magicBox.foodBox[1];
var thirdFoodItem = magicBox.foodBox[2];
var pen = magicBox.smallMagicbox.pen;
var firstFruitItem = magicBox.smallMagicbox.fruits[0];
var secondFruitItem = magicBox.smallMagicbox.fruits[1];
var thirdFruitItem = magicBox.smallMagicbox.fruits[2];
var fourthFruitItem = magicBox.smallMagicbox.fruits[3];
This is how we have been coding for a long time. Well, not any more. ES6 is our savior with its awesome feature called Destructuring. It gives us the ability to bind properties to as many variables as we need and it works with both Arrays and Objects. We will discuss this in the next section. We will learn step by step how we can extract all the properties in a single line rather than 10 separate statements.
How It Works?
Let's say we want to extract books and toys count from the magicBox
object. With ES6 destructuring, we do it like this:
var magicBox = {
book: 2,
toy: 5,
foodBox: ['pizza', 'chocolate', 'ice cream'],
smallMagicbox: {
pen: 3,
fruits: ["apple", "mango", "banana", "grape"]
}
};
var {book, toy} = magicBox;
console.log(book);
console.log(toy);
Let's take a look at this line:
var {book, toy} = magicBox;
The left side of the assignment is known as object pattern. Here, we have to give the same name as object property inside curly bracket. This will assign the magixBox
object's matched property values to variables with the same name within parent scope.
Now one may say:
Oh come on! I don't want my variables to have the same name as the object property.
Well, destructuring has a solution for this as well. To assign values to a separate named variable, we have to write it like this:
var magicBox = {
book: 2,
toy: 5,
foodBox: ['pizza', 'chocolate', 'ice cream'],
smallMagicbox: {
pen: 3,
fruits: ["apple", "mango", "banana", "grape"]
}
};
var {book: numberOfBooks, toy: numberOfToys} = magicBox;
console.log(numberOfBooks);
console.log(numberOfToys);
The above code matches the property name "book
" and "toy
", then assigns the value to variable "numberOfBooks
" and "numberOfToys
" respectively.
With destructuring, we can pull as deep as we want into an object and extract its property value.
var magicBox = {
book: 2,
toy: 5,
foodBox: ['pizza', 'chocolate', 'ice cream'],
smallMagicbox: {
pen: 3,
fruits: ["apple", "mango", "banana", "grape"]
}
};
var {smallMagicbox: {pen}} =magicBox;
console.log(pen);
The above code demonstrates how we can extract value from smallMagicbox
object inside our magicBox
object.
Now let's take a look at how we can extract values from array.
var numbers = [1,5,9,7];
var [a,b,c,d] = numbers;
console.log(a);
console.log(b);
console.log(c);
console.log(d);
The left side of this assignment var [a,b,c,d] = numbers;
is known as array pattern. Values are assigned to variables according to their index.
Now let's try to extract values from our magicBox
food array.
var magicBox = {
book: 2,
toy: 5,
foodBox: ['pizza', 'chocolate', 'ice cream'],
smallMagicbox: {
pen: 3,
fruits: ["apple", "mango", "banana", "grape"]
}
};
var { foodBox:[firstFoodItem, secondFoodItem, thirdFoodItem] } = magicBox;
console.log(firstFoodItem);
console.log(secondFoodItem);
console.log(thirdFoodItem);
Also we can deep pull the smallMagicbox
fruit array like this:
var magicBox = {
book: 2,
toy: 5,
foodBox: ['pizza', 'chocolate', 'ice cream'],
smallMagicbox: {
pen: 3,
fruits: ["apple", "mango", "banana", "grape"]
}
};
var {smallMagicbox:
{fruits: [firstFruitItem,secondFruitItem, thirdFruitItem,fourthFruitItem ]} } = magicBox;
console.log(firstFruitItem);
console.log(secondFruitItem);
console.log(thirdFruitItem);
console.log(fourthFruitItem);
Now that we understand how to extract properties with destructuring, let's try to extract all the magicBox
properties at once.
var magicBox = {
book: 2,
toy: 5,
foodBox: ['pizza', 'chocolate', 'ice cream'],
smallMagicbox: {
pen: 3,
fruits: ["apple", "mango", "banana", "grape"]
}
};
var {book, toy, foodBox: [firstFoodItem, secondFoodItem, thirdFoodItem],
smallMagicbox:{pen, fruits: [firstFruitItem,secondFruitItem, thirdFruitItem,fourthFruitItem ]}}
=magicBox;
console.log(book);
console.log(toy);
console.log(pen);
console.log(firstFoodItem);
console.log(secondFoodItem);
console.log(thirdFoodItem);
console.log(firstFruitItem);
console.log(secondFruitItem);
console.log(thirdFruitItem);
console.log(fourthFruitItem);
Cool, isn't it?
Our magic box may not answer all the questions at a time but with ES6, JavaScript has overcome its limitation. In the next section, we will learn more about the features and usage of destructuring.
Features and Usage
Just like an object returns undefined if it does not contain a property, destructuring does the same when we try to find a property which does not exist. For example, if we try to extract a "basketball
" property from our magicBox
object, it will return undefined as it does not have any property called "basketball
".
var magicBox = {
book: 2,
toy: 5,
foodBox: ['pizza', 'chocolate', 'ice cream'],
smallMagicbox: {
pen: 3,
fruits: ["apple", "mango", "banana", "grape"]
}
};
var {basketball} = magicBox;
console.log(basketball);
Similarly, if you try to get a deeply nested property which does not exist, it will give exception.
magicBox.movieBox.SpiderMan
var {movieBox:{SpiderMan}}= magicBox;
If the pulled property is undefined, we can assign default value. So when we tried to find the "basketball
" property inside magicBox
and if it is not found, we can simply assign something to the "basketball
" variable.
var magicBox = {
book: 2,
toy: 5,
foodBox: ['pizza', 'chocolate', 'ice cream'],
smallMagicbox: {
pen: 3,
fruits: ["apple", "mango", "banana", "grape"]
}
};
var {basketball= "Big Basketball"} = magicBox;
console.log(basketball);
var {basketball:bs= "Big Basketball"} = magicBox;
console.log(bs);
One of the coolest features of destrucuring is swapping variable values without the need of the third variable.
Previously, we swapped like this:
var book = 2;
var toy =5;
var aux = book;
book = toy;
toy = aux;
using destructuring, we can easily swap like below without the need of auxiliary variable:
var book = 2;
var toy =5;
[toy,book] = [book,toy];
console.log(book);
console.log(toy);
We can pull values using computed property names. Let's look at an example of ES5:
var propName = "book";
var magicBox = {book: 5};
var numberOfBooks = magicBox[propName];
In ES6, we can achieve this same result but we will need one statement less.
var propName = "book";
var {[propName]: numberOfBooks }= {book: 5};
console.log(numberOfBooks );
In terms of arrays, we can skip values and only take which we want like below:
var [,a,,b,c] = [1,2,3,4,5]
console.log(a);
console.log(b);
console.log(c);
There is a rest operator(...) to assign remaining array values to a variable:
var [a,...b] = [1,2,3,4,5];
console.log(a);
console.log(b);
Destructuring comes in really handy when we want to get some returned value from a function.
function getMember(){
return {
name : "Jonh",
age: 25
};
}
var {name,age} = getMember();
console.log(name);
console.log(age);
We can use default values for function parameter.
function sum({num1=0, num2=0}){
return num1+num2;
}
var result= sum({num2: 5});
console.log(result);
result = sum({});
console.log(result);
If we want to make the whole parameter object optional, then we write it like this:
function sum({num1=0, num2=0}={}){
return num1+num2;
}
result = sum();
console.log(result);
There are two levels of default value assignment here. Once there is no parameter passed, the function parameter is set to empty object. Again, when no property is found in empty object, num1
and num2
then set to 0
;
One of the powerful features of ES6 is For of iteration with destructuring. Let's take a look at the example below:
var employeeList = [{
name: 'John',
department: {
name: 'Finance',
managerName: 'Steve'
}
},
{
name: 'Mark',
department: {
name: 'Humar Resource',
managerName: 'David'
}
}
]
for({name: n, department:{name: d, managerName: m }} of employeeList){
console.log("Name:" +n);
console.log("Department:" +d);
console.log("ManagerName:" +m);
}
Notice how easily we are iterating the list and extracting the values we need in a single go. Just imagine the hassle we had to take previously to retrieve the three properties. Something like this:
for(var i=0;i<employeeList.length;i++)
{
var n= employeeList[i].name;
var d= employeeList[i].department.name;
var m= employeeList[i].department.manager;
}
That's all for this article. All the examples are included in the download file. You can easily check from there as well. Did you like the features of destructuring? Like it or not, this will be highly used in JavaScript programming in the near future. Therefore, I would suggest you start learning more about destructuring and other features of ECMAScript 6.
Quick Tip For Practise
Just open a latest Google Chrome browser. Go to https://jsfiddle.net/. On the JavaScript section, copy paste the code and press run. See the result in browser console. Enjoy! :)
Conclusion
ECMAScript 6 (ES6) is still not fully supported by all modern browsers, but it will eventually be adopted everywhere. This is the way how JavaScript will be coded in the near future. Therefore, it is the perfect time for us to get familiar with its features. Destructuring is one of its coolest features.