So many answers doing half the work. Yes, !!X
could be read as "the truthiness of X [represented as a Boolean]". But !!
isn't, practically speaking, so important for figuring out whether a single variable is (or even if many variables are) truthy or falsy. !!myVar === true
is the same as just myVar
. Comparing !!X
to a "real" Boolean isn't really useful.
The only thing you gain with !!
is the ability to check the truthiness of multiple variables against each other in a repeatable, standardized (and JSLint friendly) fashion.
Simply casting :(
That is...
0 === false
is false
.
!!0 === false
is true
.
The above's not so useful. if (!0)
gives you the same results as if (!!0 === false)
. I can't think of a good case for casting a variable to Boolean and then comparing to a "true" Boolean.
See "== and !=" from JSLint's directions (note: site has changed; this is an archived copy) for a little on why:
The == and != operators do type coercion before comparing. This is bad because it causes ' \t\r\n' == 0 to be true. This can mask type errors. JSLint cannot reliably determine if == is being used correctly, so it is best to not use == and != at all and to always use the more reliable === and !== operators instead.
If you only care that a value is truthy or falsy, then use the short form. Instead of
(foo != 0)
just say
(foo)
and instead of
(foo == 0)
say
(!foo)
Note that there are some unintuitive cases where a Boolean will be cast to a number (true
is cast to 1
and false
to 0
) when comparing a Boolean to a number. In this case, !!
might be mentally useful. Though, again, these are cases where you're comparing a non-Boolean to a hard-typed Boolean, which is, in my opinion, a serious mistake. if (-1)
is still the way to go here.
Original |
Equivalent |
Result |
Notes |
if (-1 == true) console.log("spam") |
if (-1 == 1) |
undefined |
|
if (-1 == false) console.log("spam") |
if (-1 == 0) |
undefined |
|
if (true == -1) console.log("spam") |
if (1 == -1) |
undefined |
Order doesn't matter... |
if (!!-1 == true) console.log("spam") |
if (true == true) |
spam |
better |
if (-1) console.log("spam") |
if (truthy) |
spam |
still best |
And things get even crazier depending on your engine. WScript, for instance, wins the prize.
function test()
{
return (1 === 1);
}
WScript.echo(test());
Because of some historical Windows jive, that'll output -1 in a message box! Try it in a cmd.exe prompt and see! But WScript.echo(-1 == test())
still gives you 0, or WScript's false
. Look away. It's hideous.
Comparing truthiness :)
But what if I have two values I need to check for equal truthiness/falsiness?
Pretend we have myVar1 = 0;
and myVar2 = undefined;
.
myVar1 === myVar2
is 0 === undefined
and is obviously false.
!!myVar1 === !!myVar2
is !!0 === !!undefined
and is true! Same truthiness! (In this case, both "have a truthiness of falsy".)
So the only place you'd really need to use "Boolean-cast variables" would be if you had a situation where you're checking if both variables have the same truthiness, right? That is, use !!
if you need to see if two variables are both truthy or both falsy (or not), that is, of equal (or not) truthiness.
I can't think of a great, non-contrived use case for that offhand. Maybe you have "linked" fields in a form?
if (!!customerInput.spouseName !== !!customerInput.spouseAge ) {
errorObjects.spouse = "Please either enter a valid name AND age "
+ "for your spouse or leave all spouse fields blank.";
}
So now if you have a truthy for both or a falsy for both spouse name and age, you can continue. Otherwise you've only got one field with a value (or a very early arranged marriage) and need to create an extra error on your errorObjects
collection.
Though even in this case, the !!
really is superfluous. One !
was enough to cast to a Boolean, and you're just checking equality.
EDIT 24 Oct 2017, 6 Feb 19:
Third-party libraries that expect explicit Boolean values
Here's an interesting case... !!
might be useful when third-party libraries expect explicit Boolean values.
React
For instance, False in JSX (React) has a special meaning that's not triggered on simple falsiness. If you tried returning something like the following in your JSX, expecting an int in messageCount
...
{messageCount && <div>You have messages!</div>}
... you might be surprised to see React render a 0
when you have zero messages. You have to explicitly return false for JSX not to render. The above statement returns 0
, which JSX happily renders, as it should. It can't tell you didn't have Count: {messageCount}
.
One fix involves the bangbang, which coerces 0
into !!0
, which is false
:
{!!messageCount && <div>You have messages!</div>}
JSX' documentation suggests you be more explicit, write self-commenting code, and use a comparison to force to a Boolean.
{messageCount > 0 && <div>You have messages!</div>}
I'm more comfortable handling falsiness myself with a ternary --
{messageCount ? <div>You have messages!</div> : false}
TypeScript
The same deal in TypeScript: If you have a function that returns a Boolean (or you're assigning a value to a Boolean variable), you [usually] can't return/assign a boolean-y value; it has to be a strongly typed boolean. This means, iff myObject
is strongly typed, return !myObject;
works for a function returning a Boolean, but return myObject;
doesn't. You have to return !!myObject
(or cast to the proper Boolean another way) to match TypeScript's expectations.
The exception for TypeScript? If myObject
was an any
, you're back in JavaScript's Wild West and can return it without !!
, even if your return type is a Boolean.
Keep in mind that these are JSX and TypeScript conventions, not ones inherent to JavaScript.
But if you see strange 0
s in your rendered JSX, think loose falsy management.