Write Cleaner Code by Using JavaScript Destructuring

bajcmartinez

Juan Cruz Martinez

Posted on July 16, 2020

Write Cleaner Code by Using JavaScript Destructuring

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
  • Doing a deep or nested destructuring
const { author: { name } } = article

console.log(name)
console.log(author)

------------------------
Output
------------------------
Juan
Uncaught ReferenceError: author is not defined
Enter fullscreen mode Exit fullscreen mode

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" }}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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]
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
[]
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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

💖 💪 🙅 🚩
bajcmartinez
Juan Cruz Martinez

Posted on July 16, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

The Accessor Protocol
javascript The Accessor Protocol

August 6, 2024

The Renaissance of Meteor.js
javascript The Renaissance of Meteor.js

July 26, 2024

Eager loading vs lazy loading
javascript Eager loading vs lazy loading

December 18, 2023

Understanding require function (Node.js)
javascript Understanding require function (Node.js)

October 3, 2023