Master Destructuring in JavaScript
Learn everything there is to know about destructuring arrays and objects in ES6
Moving From ES5 to ES6
Object and array destructuring is something that we’ve been using for a while now. We may have taken it for granted because in ES5 we needed to do something like this when we wanted to assign object properties to external variables:
function foo(){
return {a:1, b:2, c:3};
}var tmp = foo(), a = tmp.a, b = tmp.b, c = tmp.c;
We had to call the function and then assign the properties’ values to new variables.
Along came ES6 and we could simplify this using destructuring.
var { a, b, c } = foo();console.log( a, b, c ); // 1 2 3
Without needing a temporary variable, we could simply call the function, and with some new syntax, we were able to immediately capture the values of objects’ properties. Of course, this also works for arrays in an identical way:
function foo() {
return [1,2,3];
}var [a, b, c] = foo();console.log( a, b, c ); // 1 2 3
Now that we have caught up with the basics, let’s see how we can get the most out of destructuring.
Value -> target
When destructuring, you have to understand what really happens.
var { a, b, c } = foo();
console.log(a, b, c); // 1 2 3
var { a:a, b:b, c:c } = foo();
console.log(a, b, c); // 1 2 3
These two ways of destructuring are identical. We could rewrite it to something like this:
var { a:x, b:y, c:z } = foo();
console.log(x, y, z); // 1 2 3
When we declare new objects, we define them like this: var o = { a: 1 };
. Here a
is our target variable and 1 is the value we assign to that target. With destructuring it’s the inverse that is happening: x
is our target and a
becomes the value we assign to that target. So instead of “target: value,” destructuring objects are written as “value: target.” Knowing this will allow us to better understand destructuring statements in the following sections.
Default values
Sometimes the objects you’ll destructure will not have specific fields. Instead, you might want to give that field a specific value.
var { blogId, blogText, blogComments = [] } = getMostRecentBlog();
In the example above, if no comments are available on a blog we will always destructure so that blogComments
has an empty array. This can be useful in React where you might just want to render the list by calling the map function without having to make sure it’s not undefined!
We can even go further with this, e.g.:
var a = 100, b = 200, c = 300;
var dummyObject = { a : { b : 400}, b : { c : a } };( { a: a = { b: b } } = dummyObject );
( { b: c = { b: c } } = dummyObject );
( { c: b = { b: c } } = dummyObject );
Can you figure out the eventual values of a
, b
, and c
? This example shows that sometimes destructuring might get really tricky for the next reader to understand. It is important to realize that destructuring was created to make everything more readable. Here, however, we might argue that it is not. Whether you would use something like this in your code is for you to decide.
Also, note the ( .. )
around the destructuring pattern. This is necessary because otherwise, the curly braces are mistakingly considered as the beginning of a block statement instead of an object.
If you took the time to calculate the values, the result was a
= {b: 400}
, b
= {b:{c: 100}}
, and c
= {c: 100}
.
Unassigned values
When we use default values it’s because we want to ensure that the object that we’re destructuring always returns a value for a property. However, sometimes there are properties that we don’t want to capture the value of.
As you can see it is possible to destructure the object into fewer assignments. This allows us to filter out data we don’t need. Notice that with arrays, we have to use commas to skip over an element.
We can also use the spread operator in arrays to capture sub-arrays.
var dummyArray = [ 1, 2, 3, 4, 5 ];
var [a, ...b, c] = dummyArray;
console.log(a, b, c); // 1 [2, 3, 4] 5
Using the spread operator we were able to capture the first, last, and all elements in between.
Swapping variables
One of the many uses of destructuring is the swapping of variables. Most times when developers need to swap variables, they’ll assign one of the values to a temporary variable and then copy over the values. With destructuring, we can do this much more easily.
This is a nice little tool in your toolbelt. Someday we might see this appear in new languages as well.
Chaining assignments
When destructuring an object, a chain of assignments always has the full value of the object/array we’re destructuring. Consider this:
var arr = [ 1, 2, 3 ];
var a, b, c;[a, b] = [c] = [1,2,3];
console.log(a, b, c); // 1 2 3
The same is possible for objects by doing the following:
var dummyObject = { a:1, b:2, c:3 };
var a, b, c;{ a } = { b, c } = dummyObject;
console.log(a, b, c); // 1 2 3
Nested destructuring
Finally, it is possible to nest our destructuring statements. Consider this example:
var dummyObject = { a: { b : 100 } };
var { a : { b: b } } = dummyObject;
console.log(b); // 100// same as
var { a : { b } } = dummyObject;
Remember our “value: target” notation from earlier? When you want to go deep into an object’s values, you can use nesting. In the example above we have our value a
, which we assign to our target { b: b }
, which is a new destructuring statement. So then we assign the objects’ value of a.b
to a new variable called b
. (Shorthand: This assignment can also be written as { b }
.) How nice is this? We can now go as deep as we want!
An actual example would be this in which we try to get the blogTitle
of the first blog a user has written. Try to really understand this example. Once it clicks you’ll be able to take on anything using destructuring.
Conclusion
In this article, we have gone over everything there is to know to use destructuring in the best way possible. Always remember that readability is key. If you’re having trouble reading your own destructuring assignment, there might be a better solution.
I hope you learned something and that some of this helped you become a better JavaScript developer. Good luck!