Destructuring is one of my favorite tools in JavaScript, in simple terms, destructuring allows you to break down a complex structure (like an array or an object) into simpler parts, though there's a bit more than just that.
Let's see it better in an example,
const article = {
title: "My Article",
rating: 5,
author: {
name: "Juan",
twitter: "@bajcmartinez"
}
}
// Now lets print it to the screen
console.log(`"${article.title}" by ${article.author.name} had ${article.rating} stars`)
// But using destructuring, we can achieve the same by doing
const { title, rating, author: { name } } = article
console.log(`"${title}" by ${name} had ${rating} stars`)
------------------------
Output
------------------------
"My Article" by Juan had 5 stars
"My Article" by Juan had 5 stars
Now, some people have been using this feature for some time, perhaps white building React apps, but they don't quite understand it, for others it may be the first time. So I'll guide you from the start so that by the end of the article we all have the same level of understanding.
Destructuring objects
In the example above, all the magic happens at the following line:
const { title, rating, author: { name } } = article
Now it may seem a bit weird to have those brackets like that on the left side of the assignment, but that's how we tell JavaScript that we are destructing an object.
Destructuring on objects lets you bind to different properties of an object at any depth. Let's start with an even simpler example:
const me = {
name: "Juan"
}
const { name } = me
In the case above, we are declaring a variable called name
which will be initialized from the property with the same name in the object me
, so that when we evaluate the value of name
we get Juan
. Awesome! This same can be applied to any depth, to which heading back to our example:
const { title, rating, author: { name } } = article
For title
and rating
it's exactly the same as we already explained, but in author
, things are a bit different. When we get to a property which is either an object or an array, we can choose whether to create a variable author
with a reference to the article.author
object, or we can do a deep destructuring and get immediate access to the properties of the inner object.
- Accessing the object property
const { author } = article
console.log(author.name)
------------------------
Output
------------------------
Juan
- Doing a deep or nested destructuring
const { author: { name } } = article
console.log(name)
console.log(author)
------------------------
Output
------------------------
Juan
Uncaught ReferenceError: author is not defined
Wait, what? If I destructed author
, why is it not defined? What is going on is actually simple, when we ask JavaScript to also destruct the author
object, that binding itself is not created and instead we get access to all the author
properties we selected. So please always remember that.
- Spread operator (...)
const article = {
title: "My Article",
rating: 5,
author: {
name: "Juan",
twitter: "@bajcmartinez"
const { title, ...others } = article
console.log(title)
console.log(others)
------------------------
Output
------------------------
My Article
> {rating: 5, author: {name: "Juan", twitter: "@bajcmartinez" }}
Additionally, we can use the spread operator ...
to create an object with all the properties which did not get destructed.
If you are interested in knowing, check out my article on the Spread Operator in JavaScript.
Renaming properties
One great property of destructing is the ability to choose a different name for the variable to the property we are extracting. Let's look at the following example:
const me = { name: "Juan" }
const { name: myName } = me
console.log(myName)
------------------------
Output
------------------------
Juan
By using :
on a property we can provide a new name for it, in our case newName
. And then we can access that variable in our code. It's important to notice that a variable with the original property name
, in our case name won't be defined.
Missing properties
So what would happen if we try to destructure a property that is not defined in our object?
const { missing } = {}
console.log(missing)
------------------------
Output
------------------------
undefined
In this case, the variable is created with value undefined
.
Default values
Expanding on missing properties, it's possible to assign a default value for when the property does not exist, let's see some examples of this:
const { missing = "missing default" } = {}
const { someUndefined = "undefined default" } = { someUndefined: undefined }
const { someNull = "null default" } = { someNull: null }
const { someString = "undefined default" } = { someString: "some string here" }
console.log(missing)
console.log(someUndefined)
console.log(someNull)
------------------------
Output
------------------------
missing default
undefined default
null
some string here
In the example above we demonstrated some examples of assigning default values to our destructions. The default values are only assigned when the property is undefined
. If the value of the property is for instance null
or a string
the default value won't be assigned, but the actual value of the property.
Destructuring arrays and iterables
We already saw some examples of destructuring objects, but the same can apply to arrays or iterables in general. Let's start with an example
const arr = [1, 2, 3]
const [a, b] = arr
console.log(a)
console.log(b)
------------------------
Output
------------------------
1
2
The example is self-explanatory when we need to destruct an array we need to use []
instead of {}
, and we can map each position of the array with a different variable. But there are some nice tricks
Skipping elements
By using the ,
operator, we can skip some elements from the iterable as follows:
const arr = [1, 2, 3]
const [a,, b] = arr
console.log(a)
console.log(b)
------------------------
Output
------------------------
1
3
Not how leaving empty between ,
skips the elements, it's subtle but has big consequences in the results.
What else can I do? You can also use the spread operator ...
as follows:
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
const [a,, b, ...z] = arr
console.log(a)
console.log(b)
console.log(z)
------------------------
Output
------------------------
1
3
(7) [4, 5, 6, 7, 8, 9, 10]
In this case, z
will get all the values after b
as an array. Or maybe you have a more specific need, and you want to destruct specific positions in the array, no problem, JavaScript got you covered:
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
const { 4: fourth, 9: ninth } = arr
console.log(fourth)
console.log(ninth)
------------------------
Output
------------------------
5
10
If we destruct an array as if it were an object, we can use the indexes as properties and thus access any position within the array.
Missing properties
As was the case of objects, it is also possible to set default values for undefined elements in the array. Let's take a look at some examples:
const [missing = 'default missing'] = []
const [a, b, c = "missing c", ...others] = [1, 2]
console.log(missing)
console.log(a)
console.log(b)
console.log(c)
console.log(others)
------------------------
Output
------------------------
default missing
1
2
missing c
[]
For destructing arrays, it is also possible to set default values for undefined
properties, however, it is not possible to set a default when we have the spread operator ...,
which in the case of undefined
, will return an empty array.
Swapping variables
This is a fun use case of destructuring, 2 variables can be swapped in one single expression:
let a = 1
let b = 5
[a, b] = [b, a]
console.log(a)
console.log(b)
------------------------
Output
------------------------
5
1
Destructuring with computed properties
Until now, any time we wanted to destruct the properties of an object, or the elements of an iterable, we used static keys. If what we want are dynamic keys (as those stored on a variable) we need to use computed properties.
Here is an example:
const me = { name: "Juan" }
let dynamicVar = 'name'
let { [dynamicVar]: myName } = me
console.log(myName)
------------------------
Output
------------------------
Juan
Pretty awesome right! By using a variable between []
, we can evaluate its value before doing the assignment, and thus it's possible to do dynamic Destructuring, though it is mandatory to provide a name for this new variable.
Destructuring function arguments
Destructing variables can be placed anywhere we can declare variables, for example by using let
, const
or var
, but it's also possible to deconstruct in function arguments. Here is a simple example of the concept:
const me = { name: "Juan" }
function printName({ name }) {
console.log(name)
}
printName(me)
------------------------
Output
------------------------
Juan
Very simple and elegant. Also all the same rules we discussed before apply.
Conclusion
Destructuring may seem awkward at the beginning, but once you get used to it, there's no way back. It can really help your code be more readable and it's a great concept to know.
Did you know you can also use destructuring while importing modules? Check out my article An Intro to JavaScript Modules to learn more.
I really hope you enjoyed this reading, and remember, if you want to learn more about programming and AI, you can subscribe or follow me on twitter.
Thanks for reading!
If you like the story, please don't forget to subscribe to our free newsletter so we can stay connected: https://livecodestream.dev/subscribe
Top comments (2)
Great post, very useful!
ps: I think you forgot some code in "Swapping variables".
Thanks for letting me know, it is now fixed. I had it right on my code, but apparently, when I copy and pasted for the post I deleted accidentally.