DEV Community

Cover image for JS: Destructuring
Anthony Petrides
Anthony Petrides

Posted on

JS: Destructuring

A deep dive into the powerful world of javascript destructuring

Jump to:


Array Destructuring

Take the arrays called alphabet and numbers below.

const alphabet = ['A', 'B', 'C', 'D', 'E', 'F']
const numbers = [1, 2, 3, 4, 5, 6]
Enter fullscreen mode Exit fullscreen mode

To destructure alphabet, you simply set what you want to destructure equal to the name of the array as follows:

const [a, b, c] = alphabet
Enter fullscreen mode Exit fullscreen mode

Note that we wrap a, b and c in square brackets purely because we are destructuring an array. Had we been destructuring an object, they'd be wrapped in curly braces { }. We'll touch more on this later on.
For now, we have destructured the first 3 elements of the alphabet array, into variables called a, b and c. To prove this, if we run the below:

console.log(a);
console.log(b);
console.log(c);
Enter fullscreen mode Exit fullscreen mode

We would get back in our development console:

A
B
C
Enter fullscreen mode Exit fullscreen mode

What if I want to skip element?

If you wanted to, for example, skip the second element, you could simply leave an empty comma , when destructuring per below:

const [a,, c] = alphabet
Enter fullscreen mode Exit fullscreen mode

Now logging the following:

console.log(a);
console.log(b);
console.log(c);
Enter fullscreen mode Exit fullscreen mode

Would return:

A
C
Enter fullscreen mode Exit fullscreen mode

What if I want the rest of the array?

If you wanted to print the rest of the array while destructuring, because maybe you want to return the array without the first element for example, you can do this by combining the spread operator ...

const alphabet = ['A', 'B', 'C', 'D', 'E', 'F']
const [,b, ...restOfTheElements] = alphabet
Enter fullscreen mode Exit fullscreen mode

So in the above example, we destructure the alphabet on the second line, skipping the first element (as marked by the empty comma ,) then we assign the second element's value to b, and then we use the spread operator (...) to say we want the rest of the elements in the array thereafter. You need to suffix the spread operator (...) with the name you'd like to give the rest of the array. Above we've simply called it 'restOfTheElements'.

Now, What does this look like?

console.log(b);
console.log(restOfTheElements);
Enter fullscreen mode Exit fullscreen mode

Would return:

B
['C', 'D', 'E', 'F']
Enter fullscreen mode Exit fullscreen mode

Combining 2 Arrays

You can also use the spread operator to combine 2 arrays together per the below example:

const combinedArray = [...alphabet, ...numbers]
console.log(combinedArray);
Enter fullscreen mode Exit fullscreen mode

This would return:

['A', 'B', 'C', 'D', 'E', 'F', 1, 2, 3, 4, 5, 6]
Enter fullscreen mode Exit fullscreen mode

Granted this isn't the most useful feature when it comes to arrays, given you could achieve the same with:

const combinedArray = alphabet.concat(numbers)
Enter fullscreen mode Exit fullscreen mode

However, this will come in handy when we touch on combining 2 or more objects together later on.


Destructuring with Functions

Lets take the below example:

function addAndMultiply(a, b) {
    return [a+b, a*b];
}

const array = addAndMultiply(4, 2);

console.log(array) //returns [6, 8]
Enter fullscreen mode Exit fullscreen mode

We can apply array destructuring here per below:

function addAndMultiply(a, b) {
    return [a+b, a*b];
}

const [sum, multiply] = addAndMultiply(4, 2);

console.log(sum) //returns 6
console.log(multiply) //returns 8
Enter fullscreen mode Exit fullscreen mode

What we're saying here is that we are destructuring the return from addAndMultiply(4, 2) as two different variables - one called sum, and one called multiply. Again, we destructure with [ ] because the return of addAndMultiply(4, 2) is an array, and we destructure into variables 'sum' and 'multiply' in that order, because that is the order that are returned in within the 'addAndMultiply' function.


Destructuring with Default Values

We can also take the previous example and demonstrate destructuring with default values. For example:

function addAndMultiply(a, b) {
    return [a+b, a*b];
}

const [sum, multiply, subtract = 'Subtraction Default'] = addAndMultiply(4, 2);

console.log(sum) //returns 6
console.log(multiply) //returns 8
console.log(subtract) // returns 'Subtraction Default'
Enter fullscreen mode Exit fullscreen mode

Object Destructuring

The true power of destructuring in Javascript

Take the two simply objects below, personOne and personTwo:

const personOne = {
    name: 'Naruto',
    age: 29,
    address: {
        city: 'Tokyo'
        country: 'Japan'
    }
}

const personTwo = {
    name: 'Sasuke',
    age: 28,
    address: {
        city: 'Osaka'
        country: 'Japan'
    }
}
Enter fullscreen mode Exit fullscreen mode

If we want to get the name and age of personOne, we can use destructuring as follows:

const { name, age } = personOne

 console.log(name); //returns 'Naruto'
 console.log(age); //returns 29
Enter fullscreen mode Exit fullscreen mode

Note that we wrap name and age in curly braces { } because we are destructuring an object.

And unlike array destructuring, which grabs elements in the array in sequential order, object destructuring matches by the key. I.e. name had to match name in the personOne object.

You can however rename the variable that you're destructuring if you so desire.

For example, we can destructure name from the object, but call it firstName instead as follows:

const { name: firstName, age } = personOne

console.log(firstName); //returns 'Naruto'
console.log(name); //returns nothing as we remapped the var
Enter fullscreen mode Exit fullscreen mode

Defaults

We can also still use defaults in object destructuring. Lets take personTwo for example:

const personTwo = {
    name: 'Sasuke',
    age: 28,
    address: {
        city: 'Osaka'
        country: 'Japan'
    }
}

const { name: firstName, age, job = 'Shinobi' } = personTwo

console.log(firstName); //returns 'Sasuke'
console.log(age); //returns 28
console.log(job); //returns 'Shinobi'
Enter fullscreen mode Exit fullscreen mode

Above we can see we've added a property called job to the destructuring, and although it doesn't exist in the personTwo object, it has a default value set so it does return the value.

Similarly, if we added job to the object, it's default value would be overridden as follows:

const personTwo = {
    name: 'Sasuke',
    age: 28,
    job: 'ninja',
    address: {
        city: 'Osaka'
        country: 'Japan'
    }
}

const { name: firstName, age, job = 'Shinobi' } = personTwo

console.log(firstName); //returns 'Sasuke'
console.log(age); //returns 28
console.log(job); //returns 'ninja'
Enter fullscreen mode Exit fullscreen mode

You can even add defaults to renamed object variables too, per the below example:

const personTwo = {
    name: 'Sasuke',
    age: 28,
    job: 'ninja',
    address: {
        city: 'Osaka'
        country: 'Japan'
    }
}

const { name: firstName = 'Tony', age, job = 'Shinobi' } = personTwo

console.log(firstName); //returns 'Sasuke'
Enter fullscreen mode Exit fullscreen mode

As you can see above, we have name remapped to firstName, and have then also given it a default value of 'Tony'. Meaning if the name property did not exist within the personTwo object, then console.log(firstName) would return the default 'Tony'.


Spreading

We can also use the spread operator here (just like we did with array destructuring) in order to get back the rest of the object. For example:

const personTwo = {
    name: 'Sasuke',
    age: 28,
    job: 'ninja',
    address: {
        city: 'Osaka'
        country: 'Japan'
    }
}

const { name: firstName = 'Tony', age, ...rest } = personTwo

console.log(firstName); //returns 'Sasuke'
console.log(age); //returns 28

console.log(rest); 
//returns { job: "ninja", address: {city: "Osaka", country: "Japan"}}
Enter fullscreen mode Exit fullscreen mode

As you can see, we've spread the rest of the object after destructuring the age, and we've mapped it to a variable called 'rest'. So when we log 'rest', we get the remainder of the object.


Destructuring Nested Objects

We can also destructure nested objects.
Let's say we want to get only the city from personTwo. We can do this as follows:

const personTwo = {
    name: 'Sasuke',
    age: 28,
    job: 'ninja',
    address: {
        city: 'Osaka'
        country: 'Japan'
    }
}

const { name: firstName = 'Tony', address: { city } } = personTwo

console.log(city); //returns 'Osaka'
Enter fullscreen mode Exit fullscreen mode

Combining Objects

We can also use destructuring to combine objects.

Below, we will create a personThree using parts of personOne and personTwo.

Note that personTwo has been shortened to just age and job for the purposes of this example.

const personOne = {
    name: 'Naruto',
    age: 29,
    address: {
        city: 'Tokyo'
        country: 'Japan'
    }
}

const personTwo = {
    age: 28,
    job: 'ninja',
}

const personThree = {...personOne, ...personTwo}
Enter fullscreen mode Exit fullscreen mode
  • Take everything inside personOne ---> put it in an object called personThree
  • Take everything inside personTwo --> also put it in the same personThree object, but overwrite anything that was already in personOne.

What does this give you?

console.log(personThree); 

//returns
const personThree = {
    name: 'Naruto',
    age: 28,
    job: 'ninja',
    address: {
        city: 'Tokyo'
        country: 'Japan'
    }
}
Enter fullscreen mode Exit fullscreen mode

As you can see, the result of personThree is a spread personOne, overridden with anything that was in personTwo when it was spread into the same object thereafter.


Object Destructuring Inside Function Arguments

Object destructuring inside of function arguments can be a powerful tool when it comes to code simplicity.

Take the below example which demonstrates passing personOne into a printPerson function, and printing some text that grabs particular attributes from the object, such as name and age in this example:

const personOne = {
    name: 'Naruto',
    age: 29,
    address: {
        city: 'Tokyo'
        country: 'Japan'
    }
}

const printPerson = (person) => {
    console.log('Name: ${person.name}. Age: ${person.age}.);
}

printPerson(personOne);
//returns
"Name: Naruto. Age: 29"
Enter fullscreen mode Exit fullscreen mode

If we used object destructuring within the function argument, we could avoid having to repeatedly prefix the attributes we want to pluck out with person.

Using object destructuring, we can rewrite the function as follows:

const printPerson = ({ name, age }) => {
    console.log('Name: ${name}. Age: ${age}.);
}

printPerson(personOne);
//returns
"Name: Naruto. Age: 29"
Enter fullscreen mode Exit fullscreen mode

As you can see, the above returns the exact same output.

What's happening exactly?

Well, as you can see we're passing in personOne to printPerson when we call the function. And in the argument of the printPerson function we're destructuring personOne saying all we want is the name and the age.

We can also add defaults to the destructured arguments as follows:

const personOne = {
    name: 'Naruto',
    age: 29,
    address: {
        city: 'Tokyo'
        country: 'Japan'
    }
}

const printPerson = ({ name, age, favouriteFood = 'Ramen'}) => {
    console.log('Name: ${name}. Age: ${age}. Favourite Food: ${favouriteFood}.);
}

printPerson(personOne);
//returns
"Name: Naruto. Age: 29. Favourite Food: Ramen."
Enter fullscreen mode Exit fullscreen mode

Above you can see we've added a default for favouriteFood which currently does not exist in personOne so is being used. But if we added it to personOne then it would not use the default we've specified per below:

const personOne = {
    name: 'Naruto',
    age: 29,
    favouriteFood: 'Takoyaki'
    address: {
        city: 'Tokyo'
        country: 'Japan'
    }
}

const printPerson = ({ name, age, favouriteFood = 'Ramen'}) => {
    console.log('Name: ${name}. Age: ${age}. Favourite Food: ${favouriteFood}.);
}

printPerson(personOne);
//returns
"Name: Naruto. Age: 29. Favourite Food: Takoyaki."
Enter fullscreen mode Exit fullscreen mode

This is arguable the single most useful section of object destructuring - specifically when using it in React projects where you'll find object destructuring is heavily used in function calls.

Thanks for sticking through to the end! :)

Top comments (1)

Collapse
 
sethearchitect profile image
The-architect

Thanks for sharing. I found this very useful.