DEV Community

Ivan Jeremic
Ivan Jeremic

Posted on

Was JavaScript Destructuring a mistake?

I think Desctructuring is the worst thing happened to JavaScript it makes codebases ugly and slow.

This for example is the popular library react-query

 const {
   data,
   error,
   isError,
   isLoading
 } = useQuery(queryKey, queryFn)

if (isLoading) {
     return <span>Loading...</span>
}

if (isError) {
     return <span>Error: {error.message}</span>
}

return <div>{data}</div>
Enter fullscreen mode Exit fullscreen mode

vs

const result = useQuery(queryKey, queryFn)

if (result.isLoading) {
     return <span>Loading...</span>
}

if (result.isError) {
     return <span>Error</span>
}

return <div>{result.data}</div>
Enter fullscreen mode Exit fullscreen mode

We save nothing and it is not cleaner, also people will always go for it and overuse it.

Before if we wanted to know what it returns we could look at the typing if you use TS or you are just one dot away and the editor autocomplete kicks in which feels correct and clean.

This also let wo weird desctructuring API's like react useState vs native LocalStorage API as an example

const [count, setCount] = useState(0);

<div>{count}</div>
<button onClick={() => setCount(50)}>Change</button>
Enter fullscreen mode Exit fullscreen mode
const storage = localStorage

storage.getItem('count')
storage.setItem('count', 50);
Enter fullscreen mode Exit fullscreen mode

this is how it could look like in a perfect world without destructuring.

const count = useState(0);

<div>{count.value}</div>
<button onClick={() => count.set(50)}>Change</button>
Enter fullscreen mode Exit fullscreen mode

Discussion (13)

Collapse
miketalbot profile image
Mike Talbot

Where is destructuring slow? Personally I love the ability to express things without needing to dereference a variable multiple times (which is also faster if you use it more than once) - plus if you are destructuring a value you know that you have the value once and it cannot have been altered in between if you make it const. Passing props is a classic example of this in something like React.

Collapse
muszeo profile image
muszeo

I think the OP's query was about readability and slowness. I agree the latter is not likely anything material to worry about. But readability, I do get, it doesn't flow that nicely. In response to your scenario dereferencing and consts etc. doesn't need to be done with destructuring. I.e. "const someVar = myObj.someAtt;" and "const { someAtt: someVar } = myObj;" are equivalent. I think it's horses-for-courses: if you need to take more than one variable out of an object in one go then destructuring is a neat and tidy way to do it. If you need context (as per my comment) then you're necessarily loosing that (regardless of whether you use destructuring or a one-at-a-time approach!) and dereferencing at the time would be easier to follow, which is what I think the OP is querying.

Collapse
miketalbot profile image
Mike Talbot

I think your example is a little tortuous for most circumstances, its rare I'd rename a variable and do it in one line, more likely:

    const {someAtt} = myObj;
Enter fullscreen mode Exit fullscreen mode

rather than

    const someAttr = myObj.someAttr;
Enter fullscreen mode Exit fullscreen mode
Collapse
muszeo profile image
muszeo

The clue is in the name; "destructuring" is, well, removing structure. It might be useful in some scenarios, where you need to pull out lots of variables in one go and use them immediately in a narrow context. You might save yourself typing a dot or maybe two. Performance wise I doubt it makes a difference, certainly nothing worthy of note. But -- you do loose something when you remove structure, i.e. context, and I think that's maybe what you're getting at? So if you're knee-deep in some big code base and a variable pops up that once-upon-a-time was created in a destructing move, then knowing the context may be way more useful than typing fewer dots. Maybe that's what you mean by "clean"? In your short example it barely matters, as the context of isLoading is obvious. But disconnect that isLoading from the result by some lines of code, whitespace and a few methods and it becomes harder to follow what isLoading is about. Keeping isLoading inside result keeps the context and might be a lot easier to follow than go hunting. This makes it a stylistic problem, possibly one you might run into if you overuse. In the big picture however -- I view this feature as useful but slightly dangerous as it's yet another thing that encourages people to think in non-OO terms. I.e. it's a deft way to incinerate encapsulation, even more so than accessors and mutators or stripping your behaviours into services or managers and turning your model entities into nothing but dumb DTOs. If you're writing streams of functional stuff, fine, go for gold. But I'd be wary in of consequences in OO-code bases; approach with caution.

Collapse
thorstenhirsch profile image
Thorsten Hirsch

I think the code is cleaner thanks to destructuring.

const [count, setCount] = useState(0);
Enter fullscreen mode Exit fullscreen mode

Sure, you need to look into the api docs to see what useState() returns, but once you have it in your code it's clear: you get count and setCount, not more nor less. Everybody who reads your code can see it.

But without destructuring everything is hidden in the count object:

const count = useState(0);
Enter fullscreen mode Exit fullscreen mode

The count object is a blackbox. You look it up in the api docs, of course, in order to write the rest of the code, but how should anybody else know? Everybody who reads your code also needs to read the api docs to see what's inside the count object.

Collapse
ivanjeremic profile image
Ivan Jeremic Author • Edited on

You need for a destructured object the docs first aswell also both are blackboxes if you are using typescript you have everything right there too instead of going to some docs.

Collapse
ahmad_butt_faa7e5cc876ea7 profile image
Ahmad • Edited on

i love destructing , all the variable assignments are in one place instead and it just helps you so much when you dont have to fully qualify the object names all the time...

result.isLoading looks fine but imagine long names and the redundant text thats there on the screen e.g LongComponentName.LongObjectName.LongPropertyName

would love to hear why you think destructuring into consts makes execution slow too

Collapse
terpinmd profile image
terpinmd

Agree that it's very likely the same execution speed. Devils advocate for variables being in one place is its arguably easier to read and reason about if the declaration is closer to where it's used

Collapse
rollergui profile image
Guilherme

I guess it’s cool the language gives us the possibility. To use it or not, it’s up to us. Many years ago I watched two senior devs argue over some php code, one of them thought the function should receive n params, the other one thought the function should receive a $data object with everything inside. There’s almost never an absolute right answer to anything

Collapse
lexlohr profile image
Alex Lohr

I think destructuring is fine for tuples (like with react's useState). But overusing it can be a recipe for confusion ("where does error come from now? Props or query?").

If you want a slightly better usage of useState without destructuring, use

const get = 0
const set = 1
const count = useState(0)
count[get]
count[set](1)
Enter fullscreen mode Exit fullscreen mode

I think it's always a good idea to be mindful of when to use destructuring and when not to.

Collapse
ahmad_butt_faa7e5cc876ea7 profile image
Ahmad • Edited on

you are trying to decouple the state from the function.... but in react, I get the feeling that they bring them together semantically because it makes more sense for the framework. Plus its inspired by functional programming, not procedural.

you gotta remember, these are components which change behaviour BASED upon state automatically in a responsive manner if desired

just my 2 cents

Collapse
wisniewski94 profile image
Wiktor Wiśniewski

When you say something is slow/fast you need to attach some performance test cases. Everything else is just an opinion.

Collapse
geforcesong profile image
George Guo

In normal cases, i like this language feature. But when i debug the code, i hate it, i can't see the original variable's real time data.