The Art of Destructuring in JavaScript
Poses the power of destructuring and conquers the world of JavaScript. Like literally, since it’s been available to devs, it is the coolest thing ever after the dark theme. To be relevant in the JavaScript gang, one has to understand the art of destructuring in JavaScript; in this article, we will adapt to the destructuring swag.
Ask any beginner who has just started their coding journey, what kind of nightmare they have; out of many, one will be the concept of destructuring in JavaScript. But the same fella after understanding what it is will start bragging about it within their JavaScript circle. Happens to most of us, the point is why it’s been so popular nowadays and why we need to know it. The answer is the way it is handling some of the very tedious tasks we have to deal with objects and arrays in JavaScript. It offers lots of solutions and cases where it can help out in a way that a normal coding style would have cost us a lot.
Let us directly jump into coding and take notes from there on what and how it is doing. For this we will consider 2 scenarios shown as follows:
- Destructuring Arrays
- Destructuring Objects
Destructuring Arrays
Arrays are awesome until you have to use the indexes to access the elements. Working with array indexes uglify your code and make it difficult for others to read and understand quickly. For this destructuring plays a vital role; we will cover the following array-based scenarios:
- Basic One
- Skipping Values
- Index Position Values
- Default Values
- Swapping Values
- Returning Values From Function
- Passing Values To Function
- With Rest Parameter
- With Spread Operator
Basic One
const wizard = ['Harry', 'Potter']
const [firstName, lastName] = wizard
console.log(firstName, lastName) // Harry Potter
The wizard array is holding the name of the wizard (first and last name). In order to take the first name and last name individually, we need to use array indexes 0 and 1 respectively. That would be an ugly way to talk, but here we are giving names to the variable instead of talking in terms of indexes.
Skipping Values
const wizard = ['Harry', 'James', 'Potter']
const [firstName, , lastName] = wizard
console.log(firstName, lastName) // Harry Potter
Here, we wanna skip the middle name which is appearing at the 1st index location; this can be done just by skipping the variable name after firstName and moving to the 2nd index location’s variable name which is lastName.
Index Position Values
const developer = ['Rajneesh', 'Mithilesh', 'Chaubey']
const { [1]: middleName } = developer
console.log(middleName) // Mithilesh
We can even pick values from the specific index location of an array as shown above. The square brackets contain the index followed by a colon and the name of the variable. Thanks to ma friend Rajneesh Chaubey for helping me to add this one (#respect).
Default Values
const address = ['Pittsburgh', 'Pennsylvania']
const [city, state, country = 'US'] = address
console.log(city, state, country) // Pittsburgh Pennsylvania US
Here, we are making the default value of the country variable to US, since our address array don’t have any country by default the country will be US.
Swapping Values
let a = 10, b = 20;
console.log(a, b); // 10 20
[a, b] = [b, a]
console.log(a, b) // 20 10
Swapping is fun with destructuring; what magically happens here is that the variable a and b are simply re-initialized with each other’s existing values.
Returning Values From Function
const getLocation = () => [18.97474, 72.82712]
const [lat, lng] = getLocation()
console.log(lat, lng) // 18.97474 72.82712
Nothing fancy here, a function is simply returning an array (latitude and longitude values), and then we are destructuring it for our own good.
Passing Values To Function
const setLocation = ([lat, lng]) => console.log('Stored:', lat, lng)
const location = [18.97474, 72.82712]
setLocation(location) // Stored: 18.97474 72.82712
Here, a function named setLocation is accepting an array, but instead of naming the array we are destructuring it and creating variables from it inside the parameter tray itself. This looks pretty hardcore!
With Rest Parameter
const languages = ['JavaScript', 'Node.js', 'C#', 'Java', 'C']
const [lang1, lang2, ...others] = languages
console.log(lang1, lang2, others)
This one is a throwback from Rest Parameter article which we had covered already. Here, we are having a language array from which we are grabbing the first 2 values while keeping the rest as is within an array named others. For the “others” arrays, we are using the rest parameter’s three dots within our destructuring operation.
With Spread Operator
const marks = [[54, 65, 93], [48, 58, 39], [85, 95, 73]]
const [[...marks1], marks2] = marks
console.log(marks[0] === marks1) // false
console.log(marks[1] === marks2) // true
Here, we are having a marks array that has different sub-array storing marks data. We are destructuring first 2 arrays and also creating new reference of the first array using spread operator. We can confirm a new reference is created using the compare operator as shown. So the marks[0] is not same as marks1 array while marks[1] is same as marks2 array. Refer Spread Operator article for spread operator.
Destructuring Objects
Objects are the coolest in JavaScript, often with some buffy projects we receive tons of properties associated with them; then things get messy and difficult to manage, and required us to create new objects out of the main object every now and then. If it happens once or twice we can bare, but in the real-life scenario, such occurrences are a lot many. For this destructuring plays a vital role; we will cover the following object-based scenarios:
- Basic One
- Property Alias
- Default Values
- Nested Objects
- Nested-Nested Objects
- Nested Arrays
- Nested Destructed Arrays
- Returning Objects From Function
- Passing Objects To Function
- With Rest Parameter
- With Spread Operator
Basic One
const person = { id: 1, name: 'John Doe', age: 21 }
const { name } = person
console.log(name) // John Doe
Sweet! broken the person object and got only the name property out of it.
Property Alias
const person = { id: 1, name: 'John Doe', age: 21 }
const { name: personName } = person
console.log(personName) // John Doe
Same as previous with the only difference is that we can have a new alias name instead of the actual property for the variable; for example, we have given the “name” property an alias that is “personName”. This is useful in cases where we already have an existing variable name with the same property name.
Default Values
const person = { id: 1, name: 'John Doe', age: 21 }
const { name, age, salary = 0 } = person
console.log(name, age, salary) // John Doe 21 0
This feature allows us to provide a default value to the newly destructured variable. For example, we are giving a default value of zero to the salary variable, but since we don’t have a salary property within the object it will create one for us. But if it already existed then the object’s property value would be considered.
Nested Objects
const address = {
id: 1,
street: 'Kulas Light',
city: 'Gwenborough',
zipcode: '92998-3874',
geo: {
lat: -37.3159,
lng: 81.1496
}
}
const { city, geo: { lat, lng } } = address
console.log(city, lat, lng)
We are having a geo location object within our address object, but destructing allows us to further destructure the nested object as shown above.
Nested-Nested Objects
const employee = {
id: 1,
name: 'Allen Green',
job: 'Clerk',
department: {
id: 1,
name: 'Accounts',
geo: {
lat: -54.4241,
lng: 32.8973
}
}
}
const { name, department: { geo: { lat, lng } } } = employee
console.log(name, lat, lng)
Complicating it even further, we can go on with it at any level of nesting without hesitating. Here, we are getting the latitude and longitude variables out of the nested object geo within the nested object department.
Nested Arrays
const post = {
id: 1,
title: 'Voluptate occaecat',
body: 'Elit eu ullamco sit elit magna id incididunt culpa.',
comments: [
{
id: 1,
body: 'Incididunt elit magna ipsum adipisicing nisi eu.'
},
{
id: 2,
body: 'Et voluptate occaecat esse esse nisi eu ullamco duis nisi sint aliquip.'
},
{
id: 3,
body: 'Deserunt ullamco aliquip veniam quis duis sunt.'
},
]
}
const { title, comments } = post
console.log(title, comments)
It works pretty normally with an array; here, “comments” is an array that can also be destructured out from the post object.
Nested Destructed Arrays
const post = {
id: 1,
title: 'Voluptate occaecat',
body: 'Elit eu ullamco sit elit magna id incididunt culpa.',
comments: [
{
id: 1,
body: 'Incididunt elit magna ipsum adipisicing nisi eu.'
},
{
id: 2,
body: 'Et voluptate occaecat esse esse nisi eu ullamco duis nisi sint aliquip.'
},
{
id: 3,
body: 'Deserunt ullamco aliquip veniam quis duis sunt.'
},
]
}
const { title, comments: [comment1, comment2] } = post
console.log(title, comment1.body, comment2.body)
Here, we are destructuring arrays while we are destructuring the object. We are creating 2 variables from the array “comments” comment1 and comment2 while we are destructuring the post object.
Returning Objects From Function
const getProduct = () => ({
id: 1,
name: 'Wildcraft Bag',
price: 1200,
color: 'Red'
})
const { id, price, color } = getProduct()
console.log(id, price, color)
Nothing to flex here, simply an object is returned from a function named getProduct() and we are destructuring it.
Passing Objects To Function
const setProduct = ({ id, name, price, color }) => console.log('Stored:', id, name, price, color)
const product = {
id: 1,
name: 'Woodland Shoes',
price: 3000,
color: 'Brown'
}
setProduct(product)
Now, this is different! Here, we are breaking out the object which is supplied to the setProduct() function within the function’s parameter tray. This one looks cool and most of the framework uses this way, like in React we can see this in the component’s props. The setProduct() function is accepting all the values of the product object except the id property (actually in real-world scenarios id is mostly auto-generated by the backend).
With Rest Parameter
const employee = {
id: 1,
name: 'Allen Green',
job: 'Clerk',
salary: 1200
}
const { id, name, ...others } = employee
console.log(id, name, others) // 1 Allen Green { job: 'Clerk', salary: 1200 }
The formula of rest parameter can also be applied to object destructuring. Here, we are taking out only id and name properties while leaving all the remaining properties to “others” objects. For further reading refer Rest Parameter.
With Spread Operator
const employee = {
id: 1,
name: 'Allen Green',
job: 'Clerk',
salary: 1200,
department: {
id: 1,
name: 'Accounts'
}
}
const { name, department: { ...department } } = employee
console.log(employee.department === department) // false
Here, we are using the spread operator to create department object but with a new reference while we are destructuring the employee object. It actually worked and we can compare the references, it will result as false. For further reading refer Spread Operator.
Git Repository
Check out the git repository for this project or download the code.
Summary
If not the rest parameter or spread operator scared me initially, but destructuring had definitely. It is worth studying since day by day the dependency on JavaScript is increasing and we need to overcome ES6 hurdles. Most of the recent JS frameworks are using it within their coding syntax it is difficult to understand it along with the framework, so it is good to separate what are default JS features and what are framework-specific features.
Hope this article helps.
Originally published at https://codeomelet.com.