Skip to main content
Ben Nadel at InVision In Real Life (IRL) 2019 (Phoenix, AZ) with: Jessica Eisner
Ben Nadel at InVision In Real Life (IRL) 2019 (Phoenix, AZ) with: Jessica Eisner

Using Double Not-Operator (!!) For Boolean Type Casting

By on

One of the best things about reading a book like the jQuery Cookbook, which was written by a collection of jQuery community experts, is that you get see all the cool little tricks that these developers use in their programming. One neat thing that I picked up from James Padolsey was the use of the double not-operator (!!) to convert truthy / falsey values into strict Boolean data types.

The not-operator (!) takes true values and makes them false or false values and makes them true. When you apply this operator to a piece of data, Javascript must type-cast that piece of data to a Boolean value before it can "not" it. By using the double not-operator, you allow the first one to make the data-type cast and not-conversion; and then, you use the second not-operator to flip the resultant Boolean back to the appropriate value.

To see this in action, take a look at the following demo. I am creating an array of truthy / falsey values and then outputting the values as true Boolean data types:

<!DOCTYPE HTML>
<html>
<head>
	<title>Double Not-Operator For Boolean Casting</title>
	<script type="text/javascript">

		// Build an array of truthy / falsey values that we will
		// output to the document in True / False format.
		var booly = [
			1,
			0,
			"foo",
			"",
			document,
			null,
			window.iAmNotDefinedAnywhere
		];


		// Now, loop over the truthy / falsy array and output the
		// elements as true Boolean values.
		for ( var i = 0, n = booly.length ; i < n ; i++ ){

			// Use the !! (double-not) operator to convert the
			// truthy/falsey value to true Boolean data type.
			document.write( !!booly[ i ] );

			// Check to see if the value is not null (null doesn't)
			// like being converted to string.
			if (booly[ i ] != null){

				document.write( " : " + booly[ i ] );

			}

			// Line break.
			document.write( "<br />" );
		}

	</script>
</head>
<body>
	<!-- Nothing here. -->
</body>
</html>

The single line of importance in the above code is this one:

document.write( !!booly[ i ] );

Here, I am getting the value within the array and then applying the not-operator to it twice. As I mentioned above, the first casts the data type to a true Boolean and then flips it; the second not-operator then re-flips it back to the appropriate Boolean value. When we run the above code, we get the following output:

true : 1
false : 0
true : foo
false :
true : [object HTMLDocument]
false
false

Pretty slick. So, why would you want to do this? Well, in jQuery, there are methods that work off of Boolean values (such as jQuery.grep() and jQuery.fn.filter()) and it's nice to have a concise way to perform such conversions. That said, James Padolsey points out in his jQuery Cookbook chapter (page 47):

In fact, the !! is not necessary because jQuery evaluates the return value into a Boolean itself, but keeping it there is still a good idea; anyone looking at your code can be absolutely sure of what you intended (it aids readability).

It might not be necessary, but I like anything that increases readability or creates a more explicit intent.

NOTE: While this demo is in Javascript, this technique should hold true for any programming language that has the concept of truthy and falsey values.

Want to use code from this post? Check out the license.

Reader Comments

1 Comments

Thanks for this. I love those little tricks that make code look pro. Though, for people that don't know them, it might be a pain to work with.

It's hard to get to get to know these tricks. I thought using the single ! to flip a value was pretty neat not so long ago. Please post more of this if you run into it. Like the short notation for IF with the ? and :.

15,674 Comments

@Niels,

You make a good point - something only increases readability IF the person reading has any idea what is going on :) In fact, when I read about the !! operator for the first time, I was like "What the heck is that?!?".

So yeah, it depends on your context. But, now that I know about it, I do like it.

5 Comments

Just for knowledge sharing:

We can even use in JavaScript, operators like === and !== (thats three equals symbols or an exclamation symbol followed by two equals symbols, in case you dint make out.) for something similar to what Ben is explaining here.

Useful if you wanted to do something like this:

if(selectedItem !== null) {
alert("Please select a value!");
}

Here, selectedItem, although could be anything(a string, an object, a null Date) - will still be converted to be comparable with a boolean type.
Similarly for the '===' operator.

This comes from the PACKT book 'Learning JQuery 1.3' by Jonathan Chaffer.

15,674 Comments

@Sreenath,

I have not used the === and !== operators before, although I have seen them used. They compare value and *type*, I believe. I'll have to give them a lookup.

5 Comments

Okay, I was slightly horribly wrong. Got the excerpt from the book 'Object Oriented Javascript' by Stoyan Stefanov:

===
Equality and type comparison:
Returns true if both operands are equal and of the same type. It's generally better and safer if you compare this way, because there's no behind-the-scenes type conversions.

Example:
1 === '1' -> false
1 === 1 -> true
-------------------
!==
Non-equality comparison without type conversion:
Returns true if the operands are not equal OR they are different types

Example:
1 !== 1 -> false
1 !== '1' -> true

-------------------

Okay, That was some good trivia for the night!

15,674 Comments

@Sreenath,

No worries - that's what having a good conversation is all about :) I tend to use the data-type-agnostic operators since Javascript just does the data-type casting implicitly. I am sure using the triple equals is more efficient and explicit, but I have not felt compelled to use it in the past.

50 Comments

I've been digging through "Object Oriented Javascript" by Stoyan Stefanov, and they mention this trick early on which is kind of cool. Even though I'd already seen it, I still picked up a few new tidbits by checking out this code.

I always assumed the document.write() method had to be within the body tags. Didn't know you could execute it from within the head tags.

Also, I like how you define the local n variable to cache the array length. I knew you could declare more than one variable within that opening block of the loop, but it never occurred to me to do it that way.

Regarding the !!, I've got a question for you. In your example, window.iAmNotDefinedAnywhere returns false as it's undefined. However, if you were to just do iAmNotDefined without the window prefix, the code will just stop dead in its tracks.

Why does it evaluate to false with the window (or document) prefix, but without it totally chokes?

50 Comments

Here's some more to think about

//create array object, objects are truthy
arr = [];
typeof arr = "object"
!!arr = true

//null object seems to be an exception to the rule
typeof null = "object"
!!null = false

//undefined type is falsey
typeof undefined = "undefined"
!!undefined = false

//when you use document prefix you
//get undefined type on undeclared vars
typeof document.nonExistentVariable = "undefined"
document.nonExistentVariable + "" = "undefined"
document.nonExistentVariable + "-Foo" = "undefined-Foo"
!!document.nonExistentVariable = false

//remove the prefix and you start getting
//errors that kill your JS flow
typeof nonExistentVariable = "undefined"
!!nonExistentVariable = JavaScript error

//declare the non-prefixed variable with no value
//and you get undefined type
var nonExistantVariable;
typeof nonExistentVariable = "undefined"
!!nonExistentVariable = false //no more JavaScript error

15,674 Comments

@Jose,

Yeah, defining multiple values in a FOR loop is pretty snazzy. That's actually another cool thing they do in the jQuery Cookbook - they really push FOR loop syntax to the extreme. Perhaps I'll put up a post just about that as it is fairly interesting.

As far as "iAmNotDefinedAnywhere", I am not sure why exactly scoping makes a difference. Perhaps the difference is the explicit vs. the implicit scope. If you explicitly scope the variable to an object like Window, then JS interprets it as an undefined key. However, if you don't scope it, it is implicitly scoped to Window, but I guess JS doesn't look at it like an undefined key, just an undefined *value*. ?? Just guessing here.

@Elijah,

I think the triple-equals is nice because it implies more about the data that is being compared (not allowing for implicit type casting).

Since jQuery deals with form values so often, I wonder if it is then considered best practice to parse numeric values out of form fields, which are inherently text-based:

if (parseInt( $( ":input" ).val() ) === 3){ .. }

... or, if form-field interaction is ok to allow implicit type casting:

if ($( ":input" ).val() == 3){ .. }

... I guess part of it is also what you're used to.

1 Comments

Wow. Great info! It's a nice information from the post and than we get a Ben "Stronger" Nadel improving on comments.

IMO, triple-equals is better than double's in most cases, but it's always important to know the differences between both, not only apply on or other. In other words, === don't make == obsolete and vice versa.

15,674 Comments

@Leo,

It's so hard to tell. I am not sure if I really know when to go with which. For instance is:

input.val() == 3

... worse than:

parseInt( input.val() ) === 3

I really don't know. The latter one, which technically more correct perhaps (depending on how you look at it), just adds more work.

I don't think implicit type conversion is wrong. In fact, I think the first one is more "intentful". Meaning, I "intent" to check equality... without the intention of data type.

2 Comments

A reason for using !== and === in javascript (and php) is when you are explicitly testing for a boolean value. When you truly want to know if it is TRUE or FALSE, you can get "fooled" by other non-boolean values getting typecast to the boolean value.

For example, you are dealing with a function that returns a numeric value, or FALSE. You need the === to distinguish between 0 and FALSE.

Many functions return true, false, or null as their success/failure indicator; and a range of values otherwise. Any time that expected range of values can be typecast to match the success/failure indicator, you need to use === or !=== when testing for that success/failure indicator.

15,674 Comments

@Edward,

Ah gotcha. That makes sense (although it makes me wonder if those return values are a bit fishy). Probably the best use-case I've seen so far, though.

2 Comments

@Ben,

I found your excellent blog by searching for a way to trap jquery json-ajax errors. You gave me what I need; I can provide an error handler to $.ajax. Thank you!

You make a good point about true/false/null as the success/failure value being a bit fishy. Remember that both PHP and Javascript have a low "barrier to entry," that is, it's easy for inexperienced programmers to get things working, without necessarily being aware of best practices. The web would be a far uglier place if that were not true!

I expect that many of us who come from strongly-typed language backgrounds (c and fortran in my case) get caught by using == rather than ===. That, of course, simply makes the error that much more embarrassing when I get caught at it :)

15,674 Comments

@Edward,

That's awesome - I'm glad I could help out! jQuery is awesome.

Now that I think about it, this kind of multi-type return value (that you discussed) is probably used a lot in event handling. An event handler, especially in jQuery, can return True / False or Null. A false return value cancels the event bubbling and default behavior. I guess the underlying framework would make quick use of the === to separate a null return from a False return.

1 Comments

The double bang might be more useful in a situation like this:

return !!foo !== !!bar;

In this case, you just want to know if foo is defined when bar isn't and vice versa.

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel