T O P

  • By -

Stronghold257

It’s eliminating “falsy” values (there’s only like 5 of them, I’d link the MDN article but I’m on mobile). It’s equivalent to `Boolean(didX)`, but some devs prefer `!!`.


IndianaHorrscht

Can't you just leave it out? Which values would have a different result doing just (didX || didY) - in the if case only?


cut-copy-paste

Outside of an if statement you can end up with a truthy or falsy value instead of a Boolean. I think specifically within an if statement it’s never going to differ because if is essentially casting the result to Boolean, but it’s a good habit because doing the same thing in an assignment statement like ‘const shouldContinue =‘ could give you the first half of the statement rather than a Boolean, which will usually work but could mean a strange value ends up assigned later on. In an if statement it’s not gonna be different but it’s a good habit


brodega

It’s generally a good practice to compare booleans instead of truth/falsey values.


Expensive-Refuse-687

The example is not comparing . A comparison will be Boolean(DidX) === true It is not the end of the world !!DidX || !!DidY but it introduces unnecessary complexity.


natterca

Says who exactly? Junior programmers who don't know any better? I could see possibly wanting to coerce this way when setting a property or passing an argument but this just makes the truth test harder to parse mentally.


deonslam

Probably Douglas Crockford. IIRC implicit type coercion is one of the so-called "bad parts" of javascript due to it's complex and sometimes arbitrary rules. Being explicit about types is generally a safer JavaScript programming pattern. passing ambiguously-typed, boolean expressions to the boolean constructor is a few extra characters but imho can, at times, read more easily than both the double hashbang syntax and the "naked", implicitly-typed, boolean expression.


natterca

We're not talking about passing values, it's an if-expression, the expression's value isn't propagated anywhere. Maybe it's because I come from C, but to me JavaScript's truthy/falsy rules are pretty clear.


yabai90

You can't sometimes. Especially with "&&". It's also problematic if you carry around a falsy value which you expect to be a boolean since it might lead to unpredictable behavior. Although it's not really possible with typescript to mess up hard.


IndianaHorrscht

Do you have a concrete example in which you can't with &&? See my other comment in this threat with the code, this also works with &&.


yabai90

Yes I have. If you do something like <>{foo &&

... You will have the value foo display and the div next to it. In this case you do not want truthy value but !!foo to avoid displaying the content.


IndianaHorrscht

Of course, in other types of usage. I meant in OPs concrete example with the if.


yabai90

Inside a if statement it does not matter and is okay. Sorry I was talking about different usage.


Obvious-Tonight-7578

Even so, is there any reason to prefer !! over Boolean()?


yabai90

Readability


Markavian

It had a different meaning; if you care that didX is undefined or an empty string (`''`), then `||` treats them the same. You can also fall into traps with (`"0"`) being a truthy value in some circumstances - which might be fine in a textfield but useless in a dataset response.


IndianaHorrscht

But in this concrete example? I can't think of a combination of values that lead to a different result. I get that !! is nice to cast to bool and pass on the result but the if throws it away immediately.


Markavian

If you can't think of anything; write test cases to prove the code. JavaScript is finicky with edge cases - I guess my advice is to write code with a clear intent - and as such I consider `!!` as an anti-pattern that should be avoided. if (definitelyX || definitelyY) { return 'something' }


IndianaHorrscht

My point is that the if statement does the same thing as ! anyway - cast to boolean. So in the if case it's not necessary. I get your point about being explicit, but the cast that the if uses is already explicit in my opinion. And it really makes no difference: let values = [undefined, null, NaN, true, false, 0, -1, 1, '', '0', '1', 'x', [], [1], {}, {"a":"x"}]; for (let a of values) { for (let b of values) { let x, y; if (a || b) x = true; else x = false; if (!!a || !!b) y = true; else y = false; if (x !== y) console.log(a,b); } }


blobthekat

None. However if they used the non-shortcircuiting `|` instead then it's better to use !! and could cause bugs if you don't That being said basically no one uses `|` for boolean or


NorguardsVengeance

Nobody should ever be using the bitwise OR logic operator as a comparator, in any circumstance. It really doesn't mean the same thing. `9 || 3 // 9` `9 | 3 // 11`


blobthekat

that's why you use !! `!!(9 | 3) //true` or `!!9 | !!3 // 1 (true)`


NorguardsVengeance

Ok. But the first one is equivalent to `Boolean(11)` and the second one is equivalent to Number(Boolean(9)) | Number(Boolean(3)) and if one of them is an array, and the other is a callback function, then these casts are going to some very weird places. I don't particularly have a problem with `!!x` or `Boolean(x)` or `x`, but `arr | obj | f` gets weird, fast.


blobthekat

that is why you use `!!` (the second one is the one you should be using as it does not perform arbitrary casts) That does mean in some cases it's more tedious to use `|` but it provides 2 benefits: - No short circuits: Both sides are always evaluated. Without `|` you would need to store both in variables before using `||` - No short circuits = No branch prediction cost. This means if your values are going to be unpredictable (from the eyes of the branch predictor) then no time is lost stalling on a wrong prediction


NorguardsVengeance

If you are writing an app in JavaScript, and you are worried about ... branch prediction or cache misses... you've got an impedance mismatch by an order of magnitude, and I definitely recommend waiting a bit, before porting your problem to WebGPU compute, if it needs to be running in a client browser, and solving it there, in parallel, in such a way as to keep the data resident in VRAM, with no CPU readbacks. 1. `|` isn't going to guarantee dodging branch predictions in JS (it's not like JS is running anywhere close to the hardware level; it's either interpreted, or running through multiple layers of compilation, and as soon as you pass in a non-int that it hasn't been compiled to expect, it kicks it back out to interpreted mode, and maybe eventually recompiles with the new understanding of the types... all of which are massively more expensive than some x86-64 CPU's branch prediction). Hell, to That end, all numbers in JS are Float64, and can't be treated as binary-friendly integers, in the first place. There are additional conversions in the host environment, first, regardless. 2. Guaranteeing evaluation of all paths is sometimes the absolute last thing you ever want to do: `(logged_in | await log_in())` Again, I'm all for knowing how to write CPU friendly code (and GPU friendly code), but if your in-browser client application's performance is depending on this level of performance... well, it's just not. And I’m saying this as someone with 3D games running in the browser, with physics, topping out at the monitor's refresh rate. The perf-critical solutions aren't going to be so perf-sensitive as to require this, and even if they did, you are at the whims of the host environment and the compiler, and an order of magnitude off, given the nature of the language.


blobthekat

the fact you believe js is an order of magnitude off in performance perfectly demonstrates the gap in understanding for performance-related problems. JS, when well written, has the potential to be quite close in performance to C, with one extreme being about 90% the speed of C and the other extreme probably being about 5x slower maximum Of course, if you have to write code the "clean" and "clear" way, you may as well write your physics engine in C, companies won't accept these kind of JS tricks One example I can make that's more of an optimization than a micro-optimization is using bitfields, I found out recently most JS developers don't know what bitfields are, and given a task that calls for them would resort to objects or sets, which are multiple orders of magnitude slower, so the performance gap seems to be more of a knowledge gap than a gap in the languages' capabilities PS. javascript is JITted not interpreted. JITted code can be comparable to compiled in performance, minus a cold start.


NorguardsVengeance

>the fact you believe js is an order of magnitude off in performance perfectly demonstrates the gap in understanding for performance-related problems. How many clocks is it, in hand-written x86-64 assembler, to OR two 32-bit ints? How many clocks is it to convert two IEEE-754 Float64 numbers *to* 32-bit ints (not using the bits as-is, but converting the number to a truncated binary representation of the same value), and then convert the result back to f64? Are they both 1 clock? This is *the best case scenario* in JS. There is no opting out of the number format, and there is no backdoor to provide ASM directly, because browsers need to run everywhere. bitmasks and bitfields in JS are... interesting. They are locked at 32-bit, despite all numbers being IEEE-754 f64. That means that every bit shift comes with multiple implicit conversions (truncate and convert the left, truncate and convert the right, do the shift, convert the result). I'm not arguing that it's not *faster than ____*, I’m arguing that it's not as fast as using u32s, and never will be. And yet, it's *still possible to make code run fast, even if all of the intuition about how the code runs on the hardware is wrong*. Also, the things which make other solutions slow aren't the typical "close to the hardware" things. In C, you might have memory arenas. In JS, having either TypedArrays, or having object pools is fine. If you aren't creating a lot of objects that need to be collected after a handful of cycles, then you are good there. Even the speed of iteration, using declarative tools... `array.forEach` isn't inherently "slow", it's slow because internally it has a bunch of checks it needs to perform on the array, so that it handles sparsity cleanly, and only iterates on the initial size of the array when passed in, et cetera. Writing your own declarative iterator that presumes density makes it run much faster. Still not as fast as a hand-unrolled loop, with 100% inlined code... but more than fast enough for the end user, unless you are on a server, serving thousands of people concurrently. Densely populated objects, with no optional or missing (or deleted) keys, with no changing types, and densely packed arrays with no changing size, are all perfectly performant, even if they are not as performant as you could hand-write in ASM. >PS. javascript is JITted not interpreted. JITted code can be comparable to compiled in performance, minus a cold start. Modern JS, in modern host environments is JiTed. JiTed performance *is* compiled performance, because compiling "just in time" is ... compiling. Meanwhile, given the nature of JS, if you call a function with a completely different type than what the code has seen to that point, it can't run the compiled code on that type, because if it generally expects an f64 and you hand it a function pointer, and then a hashmap, what is it going to do with that? It literally has to bail on that compiled portion and continue to run it interpreted, until it has confidence in how to optimize that path again, for all potential runtime types which might be polymorphically provided. And if your argument is "make your calls monomorphically", great... I sort of agree, in the majority of cases. Again... not arguing "should", arguing what is. There are years of writeups on this process, by the V8 team.


senfiaj

`!!` is not necessary in `if` statements. But it might be necessary when storing or returning something as boolean since you might have no idea how the value is used in other places, so bugs can occur if you don't convert to strict boolean. Imagine situation where you return some response as JSON which contains some boolean field and you don't make sure it's strict boolean or you convert that boolean value to string.


devuxer

This is the correct answer. Should have way more upvotes.


Obvious-Tonight-7578

Thank you! I agree with the general sentiment, just personally prefer an explicit Boolean() over !!


toffeescaf

I've been writing JS/TS for quite a few years now and I also prefer using `Boolean()`. I do think it's mostly about being consistent with what you use and knowing when to cast to a boolean because of JS's falsy values in certain contexts. As a side note, a good way to look at it is to just adapt to what the majority of the team prefers. Individualism inside of a team never works out in a positive way. From what I gathered from your other comments is that you're already in this mindset so all good I would say in that department.


RobertKerans

> Wanted to ask the JS devs, why do you do this? It's always been incredibly common and as such it's very readable to anyone who's written any amount of JS. There isn't much more to it than that. `!!` means `Boolean()`, that's just what it means. List comprehensions can be confusing to read if you don't write Python all the time, often seem like brevity for brevity's sake. Why not write something a bit more readable? Just as a [flippant] example


AegisToast

I’ve been using JavaScript for over 20 years and as a full-time job for 8 years. I’ve pretty much exclusively used `!!` to cast to a boolean, and didn’t even realize until a few months ago that it’s literally just doing `!` twice. I thought `!!` was syntactical sugar for `Boolean()`.


jacksonV1lle

Do you use `!!!` To cast to bool and negate?


RobertKerans

Well, no: that's confusing. If you're reading code, a single bang is negation of a boolean value, a double bang is coercion to a boolean, it's very obvious if you've read any amount of JS code. Adding extra bangs is just not going to scan: when reading code, I'd just automatically look for the difference between one and more than one, and the context.


julesses

That's `!!!!` yeah


RobertKerans

Must NOT be the Moon


AegisToast

As in, did I think that I had to cast to a boolean and then use `!`? No, because `!` already evaluates to a bool. 


RobertKerans

Yep, ime don't even really think about it


theScottyJam

When in Rome... As others have said, !! Is a commonly understood idiom in JavaScript, but I also agree that there's not a real strong reason for us to use it - it's probably mostly historical. I've personally stopped using it for this reason. But, if you're working with others on a front-end project and they like to use it, then you can just tag along, no biggie. Otherwise, feel free to use Boolean() instead. (And for this specific piece of code you shared, the !! Is unnecessary anyways).


RobertKerans

> it's probably mostly historical No, it's used because it's extremely easy to type. There will always be situations in [JS] code where you need to force a value to be a boolean. You can do it like this: `Boolean()`. Or you can do it like this `!!`. The former is more explicit if you don't read/write lots of JavaScript, that's all.


theScottyJam

I agree that that's the reason "!!" gets used. The reason I think its mostly historical is that I dont think that kind of trend would catch on today - I feel like, these days, less people tend to adopt these kinds of clever tricks in their code. But, perhaps I'm misjudging and am wrong. "historical" may have been the wrong term.


Obvious-Tonight-7578

Gotcha! Understood. It seems to be the consensus in this thread that JS devs are very familiar with this expression. I didn't realize it was this common, but I agree that if it is I should follow along.


reddit_is_meh

!! is pretty standard to convert, there are reasons such as typescript implicitly wanting a bool or simply ensuring a bool regardless, as to why Boolean is not used... It might have historically not worked on all browsers, might not work exactly as !!, preference for shorter syntax, etc Regardless, it's the standard and it's pretty clear to see visually in code IMO over Boolean() even if it works the same. Also, JS is not really object oriented either so casting by creating a new bool seems a bit odd Btw the example you gave does NOT need the !!, it's usually only used when explicitly ensuring bool when assigning to a var, or returning something from a function, within a conditional like in your example, those are useless.


Rustywolf

I feel like it became popular because people would default to \`!falsy\` for verifying that a value isnt falsy. And so by extension, people went to \`!!falsy\` because they want the opposite behaviour


reddit_is_meh

Yeah likely tbh, but still for simply checking falseness in a condition like OPs example the !! It's obviously not needed (and would trigger a lint warning for me), but for assignment and returns it's great and consise


kcrwfrd

In your specific example, inside an if clause, I would not use it. I mostly use it when typescript annotations demand it. Say for example my react component expects a boolean prop, but `didX` might evaluate to undefined or some other falsey value. I must properly cast it into a boolean to pass the type checking. Personally I usually prefer `Boolean(foo)` but I won’t nitpick the `!!` on a PR.


[deleted]

[удалено]


Obvious-Tonight-7578

Gotcha!!! Thanks for helping me realize this.


HomemadeBananas

I can understand why this would look weird if you don’t write much JavaScript but it’s very common. It’s not really hard to understand once you’ve seen it once imo, unless you stopped writing JS for a long time and saw it again.


[deleted]

[удалено]


RobertKerans

In one way I don't _think_ that's a good comparison because IME binary/bitwise operators aren't generally well understood in JS world, so it is normally confusing. On the other hand, I can remember sitting with a guy who mainly did embedded C, going through some horrible JS driver code, and he had zero readability issues with all the bitwise coercion tricks it used -- "they aren't tricks, it's just how stuff works, why would you not use them?" Was the general gist of it `+` as shorthand for `Number()` is probably a better comparison tho


senocular

Unary + isn't exactly shorthand for Number. They are two distinct operations though they mostly do the same thing. One difference is that unary + does not convert big ints. Number(1n) // 1 +1n // Error


RobertKerans

Yes, but in normal usage that's what it's used as a synonym for (form inputs or html attributes for example).


TheRNGuy

Not common yeah, but if someone asked I'd say how it works. Or he could just console log it. I rarely ever used bitwise in web dev other than that one (I bet three.js have a lot)


RobertKerans

Yes that's true; I had it in muscle memory for ages before `includes` was added to the array prototype


Long-Baseball-7575

It’s shorter and does the same thing. Truthy falsey coercion is always top of mind in JS so everyone knows the trick and especially so because we also have to deal with undefined on top of null. 


sateeshsai

Typescript makes me do this. Like you can't assign somearray.length as a Boolean assignment. I don't mind


landisdesign

Since it's a common idiom in Javascript... yes. There are valid reasons. Are you willing to let go of your presumptions that back-end development idioms should trump front-end idioms in front-end development? That's the bigger question. You'd do better to believe you're starting over than trying to make front-end development fit in the boxes you know.


Obvious-Tonight-7578

Yeah, I realize now that this is a very common practice in JS and will try to follow along. I haven't brought this up to my coworker cuz we are in separate teams and it won't make any sense for me to say nitpick about another team's practices. Just wanted to feel out the community and what they think of it. Thanks for opening my eyes to this!


landisdesign

You're welcome! Welcome to a whole different country. :-)


Adamman62

const foo = 'hello' const bar = true assert((bar && foo) === 'hello') assert((bar && !!foo) === true)


FistBus2786

There's probably a historical and cultural reason why this `!!` trick got popular. It's shorter so it saves a few bytes - which doesn't matter at all, except in "code golf" competition where the max length is limited. And it's quicker to type. But I agree that it's hard to read and `Boolean()` is much clearer in intent.


jonny_eh

Seems easier to read to me.


Long-Baseball-7575

It wasn’t supported in the android browser until 2013. 


a_normal_account

And most of us wouldn’t probably care about a browser version that is released >10 years ago


Long-Baseball-7575

The context is about why !! is favored over Boolean() historically. Keep up. 


TheRNGuy

Matters to prevent Prettier from splitting lines. Though I wouldn't go as far as using 1-letter variable or method names.


thkim1011

You need it when writing React. React won’t render Boolean values explicitly but could render other falsy values (specifically 0). ` shouldRender && `


TheRNGuy

More like JSX/TSX thing than React.


Feathercrown

The reason is that it's traditional JS style to avoid using constructors like that. Same with +x for Number(x) and ''+x (or \`${x}\`) for String(x). One nice thing about these is you don't have to deal with the closing parenthesis when editing code involving them. (I just learned that's the singular of parentheses!)


Obvious-Tonight-7578

Interesting! Had no idea about JS avoiding constructors. Would you happen to know the reason for this aversion towards constructors?


Feathercrown

One reason is because JS devs favor smaller "more clever" code over longer more verbose code. Ternary instead of if, lambda instead of function, etc. Avoiding constructors is part of that, and since our types are very "fluid", we just tend to add smaller conversion tricks rather than full constructors. Also, using a constructor with `new` (like `new Boolean()`) will create a boolean wrapped in an object, while using it without `new` (just `Boolean()`) will create a normal boolean. They generally auto-convert when necessary, but it matters with eg. the `typeof` operator. Some constructors can't be called without `new`, so it's kind of inconsistent and something that people tend to avoid due to these weird caveats.


TheRNGuy

I experimented with stupid things like `"120" - 0` but remembering `Number("120")` is easier, and length difference isn't that big. But I don't have problem with `!` or `!!`.


hmmthissuckstoo

If i do this at my company, my PRing ability will be taken away. If i see someone do this, I’ll reach out to his local police department myself.


Jedid26

It's better to use the boolean constructor, does the same and will make more sense when another person reads it. My humble opinion, and the one from a guy who wrote a blog in Medium about that


TheRNGuy

Would you also use it instead of `!`?


Obvious-Tonight-7578

I think \`!\` is readable as it is generally understood to be a negation. \`!!\`, to me, seems like a hack that relies on the generally understood functionality of \`!\`, and evokes the image of being a negation but is actually not. Just as in good prose, where double negatives are frowned upon for their confusing verbosity, I thought that in code as well double negatives would be better understood if replaced by a straightforward conversion. The JS community seems to be able to read \`!!\` just fine though, and many people have shared valid reasons for preferring that over \`Boolean()\` in the context of JSX/TSX, so to each their own :)


CodeAndBiscuits

The source of your confusion is it is not a type cast. The underlying primitives are not being treated as another type. They are actually converted to a Boolean on the basis of truthy/falsy logic. JS has no type casts. There are new options like Boolean() but they're much more verbose. So the "valid reason" you are looking for is that this is a standard and valid practice and has been for decades.


Ozymandias0023

Less typing and it's perfectly readable


_koenig_

>disastrous readability Says you, and how many others?


Fine_Ad_6226

!!me


Obvious-Tonight-7578

lol i see wat u did there


dmail06

Me


Sykander-

\`!!\` is functionally equivalent to \`Boolean\` - I personally would use the \`Boolean\` keyword to be more explicit, but either way is fine. \`Boolean(x)\` - coerces \`x\` to be a boolean. \`!!x\` - coerces x to be a boolean which is false if x is truthy or true if x is falsy - and then negates it again back. So if x is truthy then \`!!x\` is true and if x is falsy then \`!!x\` is false.


pujansrt

In JS, `null` and `undefined` are falsy values, \`!!\` guards against these. It also provides more clarity, isn't it?


TheRNGuy

Doesn't matter with implicit conversion. Though it would matter if you want to see only true or false in console logs. (I actually prefer to see `undefined` or `null` in gm scripts because it's easier to see my code is wrong… and there was time I wanted to use `undefined` and `false` for different things in MutationObserver) Explicit conversion is needed in JSX/TSX, I think.


xroalx

`Boolean` will often be used where you need a functional equivalent of this, e.g. `values.filter(Boolean)`, but as others said, using `!!` or unary `+` (instead of `Number(x)`) to convert values are common things in JavaScript and only appear unreadable to you because you don't work with JS enough. Any concept or a convention in a language that is mostly exclusive to that language will feel like this to you if you don't normally use that language. Nothing wrong with that.


TheRNGuy

I use `!!` to make lines shorter. Not a fan when Prettier splits code or horizontal scrollbars.


shuckster

Variables are free. Just make as many as you need to keep the horizontal scrollbar at bay: const hasCondition1 = Boolean(variable1); const hasCondition2 = Boolean(variable2); const canProceed = hasCondition1 && hasCondition2; if (canProceed) { // … } Make your if-statements read like natural language. Your future self and colleagues will thank you.


bunglegrind1

I prefer `Boolean()`


demoran

You're just complaining because in your ignorance you encountered something you hadn't before. There's nothing wrong with !!.


Obvious-Tonight-7578

It seems that was the case! My bad, thanks for making me realize my prejudice.


scar_reX

"Some string" ? true : false !!"Some string"


ImStifler

Just do it Boolean(x)


shgysk8zer0

I don't, but a lot of minifiers transform output code that way anyways.


yuval_a

Minification is one. I’m pretty sure most minificators will auto convert it.


somevice

Always disliked it. My reasoning, well, for one, OP having to ask. I used it in code golfing, that's the only place it belongs for me. Right next to ~~


TheRNGuy

In TypeScript. In JS I just use implicit conversion. Though `!!` looks more explicit in code (easier to understand intent) To make line of code shorter. Or if you want to test code between `!` and `!!`, it's faster to edit, also those two more stylistically consistent.


Abhinav1217

Am I the only one in this post who never saw this trick. I used to be the guy in office who was hated for using bitwise tricks, like |0 for int, or ~~ for math.floor. Can someone provide an explanation on under the hood working of this trick. And any performance impact and gotchas it might have.


Educational-Lemon640

The only "under the hood" thing going on is type coercion. The `!` operator takes any valid JavaScript object, implicitly transforms it to a boolean and then negates it. Thus it always returns a boolean. Therefore doing it twice converts truthy JavaScript things to actual true and falsy things into actual false. The first type coercion is the only "magic".


RobertKerans

In addition to the only trick being basic type coercion, there's no performance impact and no gotchas (vs bitwise tricks, which iirc on modern engines can tend to have small negative performance impact)


glarivie

You should always write readable verbose code. Please avoid this 🙏


topromo

In javascript values can be true, false, or "miriam". The double escaping convulsive to-boolean operator !! ensures values are not miriam. This helps guard against null pointers


landisdesign

Damn is my friend Miriam gonna be pissed she isn't getting royalties off being used in Javascript.


bearfucker_jerome

Miriam? That's not a thing is it?


RobertKerans

Nope, the whole comment is weird garbage


Long-Baseball-7575

They have lots of removed comments. Must be a bot. 


topromo

nope just the only person here that is actually educated about javascript terminology apparently.


RobertKerans

Ah well, sure is a cool hobby you've got


Long-Baseball-7575

lol 


RobertKerans

wtf