views:

3004

answers:

7

I've just walked into this code:

val.enabled = !!enable

and have no idea what does "!!" do... I googled JavaScript operators but haven't found this one.

+21  A: 

!! converts the value to the right of it to its equivalent boolean value. (Think poor man's way of "type-casting"). Its intent is usually to convey to the reader that the code does not care what value is in the variable, but what it's "truth" value is.

Crescent Fresh
Or in the case of a boolean value on the right, it does nothing.
Daniel A. White
@Daniel: `!` still flips the value to the right. In the case of a boolean the right-most `!` negates the value, while the left-most `!` negates it once again. Net effect is that there is no change, but most engines will generate op codes for the double negation.
Crescent Fresh
+17  A: 

It converts the suffix to a Boolean value.

Paul McMillan
Logical or is a double-pipe, not a double-bang
Peter Bailey
@Peter Baily: it's a logical NOT twice.
NickFitz
@NickFitz, I know that. But Paul's answer has been edited - it used to say that !! was logical or.
Peter Bailey
+55  A: 

It's a horribly obscure way to do a type conversion.

! is NOT. So !true is false and !false is true. !0 is true and !1 is false.

So you're converting a value to a bool, then inverting it, then inverting it again.

//Maximum Obscurity:
val.enabled = !!userId;

//Partial Obscurity:
val.enabled = (userId != 0) ? true : false;

//And finally, much easier to understand:
val.enabled = userId != 0;
Tom Ritter
!!false = false. !!true = true
roosteronacid
`(userId == 0) ? false : true;` hurts my brain the least.
Andy Gaskell
Yeah, I agree with Andy; using the ternary operator seems to be the clearest way. If it works (I'm not sure it does) then `var.enabled = (bool) userId;` seems pretty clear to me also.
Imagist
How about using === and !=== instead of ==/!=
Luis Abreu
@Luis Abreu: the === or !=== will not work here, becase they compare **the exact result** *without converting anything*. Then if the userId is `false` and you use `userId !== 0` then the result will be `true` which is wrong.
Protron
Horribly obscure .... beautifly concise to my eyes ....
James Westgate
Is the "much easier to understand" variant really much easier to understand here? The check against 0 is not an actual check against 0, but a check against the somewhat weird list of values Javascript considers equal to 0. `userId ? true : false`makes more clear that there is conversion going on and handles the case where userId's value might have been explicitly set to `undefined`
Ben
My brain doesn't have any problem decoding `!!var` into `Boolean(var)` .. and `!!` is faster (less instructions to process) and shorter than the alternatives.
Infinity
+10  A: 

It's a double not operation. The first ! converts the value to boolean and inverts its logical value. The second ! inverts the logical value back.

Bill the Lizard
+7  A: 

! is "boolean not", which essentially typecasts the value of "enable" to its boolean opposite. The second ! flips this value. So, !!enable means "not not enable," giving you the value of enable as a boolean.

Adam Backstrom
+5  A: 

!!foo applies the unary not operator twice and is used to cast to boolean type similar to the use of unary plus +foo to cast to number and concatenating an empty string ''+foo to cast to string.

Instead of these hacks, you can also use the constructor functions corresponding to the primitive types (without using new) to explicitly cast values, ie

Boolean(foo) === !!foo
Number(foo)  === +foo
String(foo)  === ''+foo
Christoph
But then you can run into issues with instanceof.new Boolean(1) instanceof Object -> true!!1 instanceof Object -> false
Seamus
no, you can't: notice that the constructor functions are called without `new` - as explicitly mentioned in my answer
Christoph
+1  A: 

It's not a single operator, it's two. It's equivalent to the following and is a quick way to cast a value to boolean.

val.enabled = !(!enable);
Justin Johnson