DEV Community

Cover image for Destructuring JavaScript objects like a pro

Destructuring JavaScript objects like a pro

Will Soares on June 16, 2019

Hello there! For a long time now I've been wanting to take notes on a couple of tricks I currently use at work regarding the concept of Destructur...
Collapse
 
n1ru4l profile image
Laurin Quast

You can even do this wizardry:

const object = { prop1: "value1", prop2: "value2" };

const  propName = "prop1";

// destructure dynamic property
const { [propName]: value } = object;

value === "value1" // true
Collapse
 
willamesoares profile image
Will Soares

Yes! Dynamic destructuring!
allthethings

Collapse
 
vitorreisdev profile image
Vitor Reis

js wizardry... That's pretty cool I haven't thought of that

Collapse
 
itspauloroberto profile image
Paulo Roberto Rosa

It is possible to do it nested???

Collapse
 
n1ru4l profile image
Laurin Quast

You mean the following?

const object = { prop1: "value1", prop2: { a: "abc" } };
const  propName1 = "prop2";
const propName2 = "a";
const { [propName1]: { [propName2]: value } } = object;
value === "abc" // true
Collapse
 
js2me profile image
Sergey S. Volkov • Edited

Good article, thanks ! :)

But one moment

We have small but important difference between default value of destructed property and ||

const { foo = "bar" } = baz

In this case runtime compiler (as I know) checks value only on undefined and because of this some falsy value like false or '' is not been replaced to default value "bar"

But in other case

const foo = baz.foo || "bar"

|| checks first operand on any possible falsy value and if we have .foo like null then variable will been equals to "bar"

Collapse
 
andreyvladikin profile image
Andrey Vladikin

let a = 1;
let b = 2;
[a, b] = [b, a];
=)

Collapse
 
timkor profile image
Timkor

Nice, didn't realise one could easily use this to swap variables!

Collapse
 
willamesoares profile image
Will Soares • Edited

Congrats :)
I should probably tell people not to look at comments before trying 😄

Collapse
 
merri profile image
Vesa Piittinen • Edited

I'd advice against deeply nested destructures like the given example:

const {
  classs: {
    infra: {
      name: homoSapiensInfraClass = ''
    } = {}
  } = {}
} = homoSapiens;

There is classs there, which could be a typo and it would easily go totally unnoticed.

Another point I'd like to make is that it is very hard to read the above. Just do:

const homoSapiensInfraClass = homoSapiens['class'].infra.name || ''

Or if you want to allow all objects to miss:

import get from 'lodash/get'

const homoSapiensInfraClass = get(homoSapiens, 'class.infra.name', '')

Much easier to understand what is happening. If you want to get multiple items you could use array destructuring:

const [homoSapiensInfraClass, homoSapiensFamily] = [
    'class.infra.name',
    'family'
].map(item => get(homoSapiens, item, ''))

Although this makes sense only if you have a whole lot of those. This example is good because it retains the normal reading order, while renaming while destructuring fights against the normal reading order. Rename in destructuring should be used sparingly to keep code easy to read.

Collapse
 
willamesoares profile image
Will Soares

Hey Vesa, thank you for the suggestion. I appreciate your contribution.

As for your concern on legibility I would take that more as a preference matter, I personally don't see that as a very hard thing to read but I understand your point.

I think the option you gave it's nice if you want things to explicitly fail so you'd be aware of possible typos. In a context in which you don't know what to expect for the structure of the homoSapiens object for instance I'd prefer to be safe and set default values for each object being destructured, instead of receiving errors like Cannot read property 'x' of undefined.

And yeah, if you can use lodash then go for it ;)

Collapse
 
timkor profile image
Timkor

I think it's by purpose. class is a reserved keyword. Although possible to use in some modern browser, I bet IE doesn't like this.

Collapse
 
brittanmcg profile image
Brittan McGinnis

I would agree with you. I think that just because you can doesn't necessarily mean that you should. I do appreciate the knowledge sharing though and it is interesting to see the different ways that it's possible to destructure.

Collapse
 
mckabue profile image
Kabue Charles • Edited

You actually don't need dynamic de-structuring to swap values of two variables without using any extra variable:

const { prop1: prop2, prop2: prop1 } = { prop1: "value1", prop2: "value2" }

console.log(prop1) // value2
console.log(prop2) // value1
Collapse
 
agronick profile image
Kyle Agronick

Thats cool. I didn't know you could do that with the default values. It seems backwards to me though with the variable to assign from on the left of the colon and the variable to assign to on the right.

Collapse
 
c24w profile image
Chris Watson

I found that slightly counterintuitive to start with, too, when you're used to name = value. The easiest way I find to remember the order is { from: to } = obj. Also, it wouldn't make much sense to use { to: from } = obj because you're no longer putting the from in the same position as the key is in the object.

Collapse
 
alainvanhout profile image
Alain Van Hout

A very nice explanation 😁

Just because it makes my inner biologist cringe: could you possible replace 'specie' with 'species' (because that's both the singular and the plural form: en.wiktionary.org/wiki/species)?

Collapse
 
willamesoares profile image
Will Soares

Updated! Thanks for that :D

Collapse
 
laurieontech profile image
Laurie
Collapse
 
willamesoares profile image
Will Soares

Ah yeah! Great post! The more the merrier :)

Collapse
 
laurieontech profile image
Laurie

I mean, it’s clearly one of the best bits of modern ES syntax. Everyone must know!

Collapse
 
mehdibenhemdene profile image
mehdibenhemdene • Edited

I don't know if anyone already posted this answer but from what I see must people used objects to do it instead of arrays.

My solution :

var foo = "foo";
var bar = "bar";

[bar, foo] = [foo, bar];
Collapse
 
samba_code profile image
Sam Atkinson

Did not know you could destructure an array. Very cool! Thanks for the post.

Collapse
 
timea profile image
Timea Kiss

I have one serious issue with this article -> wanna give it more than one <3s :D Thanks!

Collapse
 
willamesoares profile image
Will Soares

Thanks Timea. I'm glad you liked it 🎉

Collapse
 
sergei profile image
Sergei Sarkisian

In the complex cases it seems just like another bad spaghetti code.

But in the simple cases it’s pretty usable and clean.