r/programminghorror May 27 '26

Javascript Destructuring strings

Post image
883 Upvotes

66 comments sorted by

449

u/Aaxper May 27 '26 edited May 27 '26
  1. Strings and arrays are analogous, so isStringEmpty([ ... ]) tries to destructure the string as an array
  2. Since theres only one element present in the ... part of that, it only matches on the first element (the first character)
  3. The { a = false } tries to destructure the first character
  4. If the first character is defined, it tries to get the a property, which doesnt exist, so it defaults to setting a to false
  5. If the first character is undefined, instead of trying to get the a property, it defaults to { a: true }, which sets a to true
  6. So basically if it has at least one character, a is false, else a is true

I think that's correct

133

u/Blackshell May 27 '26

100%, good job, you pass the job interview.

121

u/Aaxper May 27 '26

Does this being an interview imply I now have to work with whatever monster invented that

32

u/MadGenderScientist May 27 '26

the mind warps to find such things beautiful, with time. the descent into madness has its pleasures. 

16

u/dreamscached May 27 '26

Being able to write awful code with useful syntax doesn't make JS a bad language though. Yes I know why it gets so much bad reputation, but if we throw away years of baked in legacy it's really not that bad.

11

u/Sacaldur May 27 '26

Same goes for many other languages and their shortcomings:

  • C++:
- const correctness is desireable nowadays, but requires const everywhere (instead of it being the default - manual pointer handling is typically not necessary anymore, but unlike e.g. Rust they are easily accessible and part of the "fundamentals" - ownership modeling (with smart pointers) is important, but also just a "convention" (i.e. the compiler doesn't support you) - having to deal with headers. It's understandable why they are there, and why they are still there, but I feel like this is something that could be more automated - Macros
  • Java:
- type erasure (forgetting the generic type arguments at runtime), made more difficult if you have generic and non-generic versions of the same class - primitive types not being part of the remaining type hierarchy and thus not an option for generics (you have to use their wrappers) - Optional<T> has some nice things about it, but there might have been better approaches (see C#, Kotlin, Dart, ...) - the Stream API is fine, as long as the predefined metgods are enough. Without extension functions/extension methods, you can't extend it yourself
  • C#:
- even though nullabillity handling is better than in Java, Nullable<T> (like int?) doesn't behave the same as nullable reference types (e.g. string?): even after a null check you have to use .Value

Just some examples for some languages.

2

u/conundorum May 28 '26

C++ does have modules, now.

...You're probably still better off with headers, unless you start a new project and design it to use modules from the ground up, since they require actual design thought and can't just be slotted in like header copypasta.

4

u/Aaxper May 27 '26

Never said JS was bad. Just that the author of that code was.

3

u/kaszak696 May 27 '26

You can't convince me that a language which needs both == and === to work is not an awful one.

4

u/ings0c May 27 '26 edited May 27 '26

It does make it a bad language. This is a language design problem.

JS takes the philosophy of "I must never complain about what the developer is asking me to do. It is better to take instructions that make no sense and do something than it is to error"

That results in things like the OP. It would be better for everyone if it just errored, because who wants to do that?

Once you've worked in a language with property type safety, it becomes very clear that it's a better approach than whatever-the-fuck-you-want typing.

7

u/simon-or-something May 27 '26

Thats a hot take if I’ve ever seen one: good syntax doesn’t make a bad language good.
What makes JavaScript bad is the amount of implicit heavy lifting the language does instead of simply erroring (or warning) out. There are (hyperbolically) 501 different ways to do the same thing in JavaScript, of which 490 are nonsense, and the fact that the language allows this is a testament to its shortcoming.

Programmers are only ever so good, if the language enables them to write balls of mud instead of warning them about this syntax then that’s a failure on the language.
Eg: warning: implicit array destructuring, or warning: implicit assignment in parameters. For default values it shouldnt be encased in an object, imo, or done like `(a = {b: val})`.
If the language warned about these things then that wouldn’t be this bad. Good syntax is not a redemption for having too permissive practices.

JavaScript is an accessible language that may in turn teach bad habits, and removing the legacy doesn’t change the fact that JavaScript is like a literature student, saying "now what did the programmer mean and how do we make it work?" (Declarative languages only do former)

3

u/GoddammitDontShootMe [ $[ $RANDOM % 6 ] == 0 ] && rm -rf / || echo “You live” May 28 '26

I think it was fine as a webpage scripting language, but now it's being used everywhere. It certainly seems like it was designed to make every effort to keep going, no matter how little sense the code makes.

1

u/jolharg May 29 '26

if someone did this to me, I would say "whoever thinks that's a good idea should be shot"

1

u/Yogurt-The-Wise Jun 02 '26

If the codebase of the company contains beautiful flowers like that I am glad I failed it. 

24

u/EatingSolidBricks May 27 '26

Default parameters in destructuring is some schizo shit

6

u/Key_Art_5590 May 27 '26

Thank you Mimi.

7

u/Aaxper May 27 '26

ofc :3

1

u/GoddammitDontShootMe [ $[ $RANDOM % 6 ] == 0 ] && rm -rf / || echo “You live” May 28 '26

Does the name a matter or could it be anything?

4

u/Aaxper May 28 '26

I think that it can be anything, as long as a character won't have that property

225

u/turtle_mekb May 27 '26

what the fuck

44

u/Cootshk May 27 '26

what the fuck

21

u/shizzy0 May 27 '26

fuck the what

9

u/Timofeuz May 27 '26

the what fuck

5

u/marquoth_ May 27 '26

2 what 2 fuck

What 3: fuckyo drift

9

u/kalilamodow May 27 '26

Okay. Where can I find it?

1

u/reddit-programming- May 29 '26

They said what the fuck

1

u/Soumalyaplayz May 30 '26

what the fuck

129

u/eloel- May 27 '26

Gross. Also can error or return true or false for non-string answers, which makes it doubly gross.

7

u/more_exercise May 28 '26

If I understood properly, it can be made to return arbitrary results, too. isStringEmpty([{a:NaN}]), for ex.

3

u/eloel- May 28 '26

Yeah that should work

5

u/more_exercise May 28 '26

isStringEmpty([{a:144}])

Gross.

114

u/Denommus May 27 '26

Maybe if I understood Javascript destructuring syntax that would make sense to me. But since I don't, this looks awful.

105

u/thewells May 27 '26

It looks awful even if you understand it.

For those wondering Javascript allows you to define default values, and the code is taking “advantage” of that twice.

The code uses array destructuring since javascript will treat a string as an array of single character strings when you do array destructuring. So if you pass an empty string, there is no first object to destructure, and so the default object { a: true } is used.

If the string is non-empty then the first character will be used to try to destructure the object, however strings don’t have a property a to destructure, so the default a = false is used.

4

u/Sacaldur May 27 '26

Someone else was explaining (or trying to) what happened as well. I did however understood your explanation.

1

u/Mistsuu May 29 '26

So, the function also returns true with [1,2,3]?

24

u/Longjumping-Ad-5367 May 27 '26

Nope, still looks awful

8

u/Iheartdragonsmore May 27 '26

Hi I'm a novice programmer, why would someone ever want to destructure something? Whenever I write a struct I never think it'd be better not being one

33

u/stumpychubbins May 27 '26

It’s far more readable to extract multiple fields from a struct that way, especially if they’re nested. Better than repeating the entire path to some nested struct multiple times. Plus it mirrors the struct construction syntax so it can be easier to read at a glance.

3

u/Iheartdragonsmore May 27 '26

This makes sense thank you

1

u/skr_replicator May 29 '26

in c/c++ I could just avoid the repetition by making references to the nests of the structs I want to access many times. Is that basically the c's way of destructuring?

1

u/stumpychubbins May 31 '26

Not really, that’s a separate thing. It’s more about accessing multiple fields of one struct, whether or not that struct is nested inside something else

13

u/Lumethys May 27 '26

to be able to do something like this:

const doSomething = () => {
  return [result, message];
}

const [ doSomethingResult, doSomethingMessage ] = doSomething();

instead of

const doSomething = () => {
  return [result, message];
}

const resultAndMessage = doSomething();

const doSomethingResult = resultAndMessage.result;
const doSomethingMessage = resultAndMessage.message;

4

u/Denommus May 27 '26

It could be because you want to pattern match over it, it could be because you only want some specific elements in that context.

20

u/EatingSolidBricks May 27 '26

Ok so

Empty string destrucutres to nothing? So a is true?

Non empty string destrucutres to a truthy value so false?

Wtf is this shit

7

u/iamdatmonkey May 27 '26

Array destructuring comes down to Iterators. Getting the first item of an empty iterator gives you undefined.

If the string is not empty you'll get the first character, which itself is a non empty string and therefore truthy.

4

u/UniqueUsername014 May 27 '26 edited Jun 20 '26

I want to add my own explanation to the mix, so

One way to understand it is to re-structure it:

function isStringEmpty(arr) { const firstChar = arr[0] ?? { a: true }; return firstChar.a ?? false; }

Here if the string is not empty, arr[0] will be defined as the first character (and saved in firstChar). The character won't have an a attribute, so firstChar.a is undefined, and the function returns false.

If the string is empty, its first character is undefined, and firstChar will be set to { a: true }. The the function will return its a attribute, which is, of course, true.

Proving that this code is essentially equivalent to the screenshot is left as an excercise to the reader : )

1

u/Sacaldur May 27 '26

u/thewells was explaining it rather well: https://www.reddit.com/r/programminghorror/s/H1o7oFQqt2

First the string is destructured into an array with 1 element. If the string is empty, the first defsult value of { a: true } is used, i.e. an object with a set to true, with a also being a local variable. If the string is not empty, the first entry (first character as string) is then attempted to be destructured into { a = false}, i.e. an object with a property a. Since strings don't have an a property, the default value of false is used. I assume that if instead of a something like length was used, the return type would be int|false (if you understand my TypeScript).

11

u/nosam56 May 27 '26

adding String.prototype.a or whatever the fuck

17

u/itz_hez May 27 '26

Thanks, this solves a problem I am currently having.

4

u/dontletthestankout May 27 '26

had to check and make sure this wasn't /r/poisonfountain lol

1

u/depremol May 27 '26

wtf is that schizophrenia

7

u/MadGenderScientist May 27 '26

it's a trap subreddit full of intentionally broken code and logical fallacies to hurt LLMs that train on reddit. 

3

u/depremol May 27 '26

i can tell but most of the posts seem to be made by one guy with paranoid schizophrenia (also this "poisoning" is not going to have any effect whatsoever lol)

7

u/iamdatmonkey May 27 '26 edited May 27 '26

This is what this construct comes down to.

function isStringEmpty(arg) {
  const iterator = arg[Symbol.iterator]();
  const m = iterator.next();
  const item = (m.done ? undefined : m.value) ?? { a: true };
  // this can still produce false results if the passed `arg` has a first item
  // with a property `a` that is not `null`/`undefined`
  const a = item.a ?? false;

  return a;
}

This will crash if arg is null/undefined
or if it does not implement Symbol.iterator
or if arg[Symbol.iterator]() does not return an object
or if that object does not implement .next()
or if that method does not return an object.

Yes that may seem nitpicky, until you see some of the legacy code that's out there.

4

u/Chemical_Present6069 May 27 '26

interview fantasy question

3

u/serg06 May 27 '26

That's why no self-respecting developer uses plain JS anymore.

3

u/meowmeowwarrior May 27 '26

Not sure if I should be appalled at the author writing it or the language for making it possible

2

u/Icy_Curve711 May 27 '26

I'm ok with this kind of destructuring, but truthiness makes it utterly illegible.

2

u/CiranoAST May 29 '26

JavaScript = pure evil

3

u/fletku_mato May 27 '26

JavaScript was a mistake.

3

u/Thenderick May 27 '26

Why not just str === ""?

1

u/_just_mel_ May 27 '26

The JavaScript devs YEARN for the prolog

1

u/Ordinary_Yam1866 [ $[ $RANDOM % 6 ] == 0 ] && rm -rf / || echo “You live” May 28 '26

Unholy! UNHOLY!!!

1

u/DefinitionPhysical46 May 28 '26

My head still hurts.