The Art of Destructuring in JavaScript

Zaki Mohammed Zaki Mohammed
May 10, 2022 | 7 min read | 1342 Views | Comments

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:

  1. Destructuring Arrays
  2. 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:
  1. Basic One
  2. Skipping Values
  3. Index Position Values
  4. Default Values
  5. Swapping Values
  6. Returning Values From Function
  7. Passing Values To Function
  8. With Rest Parameter
  9. 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:
  1. Basic One
  2. Property Alias
  3. Default Values
  4. Nested Objects
  5. Nested-Nested Objects
  6. Nested Arrays
  7. Nested Destructed Arrays
  8. Returning Objects From Function
  9. Passing Objects To Function
  10. With Rest Parameter
  11. 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.


Zaki Mohammed
Zaki Mohammed
Learner, developer, coder and an exceptional omelet lover. Knows how to flip arrays or omelet or arrays of omelet.