Can someone explain this 'double negative' trick?

JavascriptHtml

Javascript Problem Overview


I am by no means an expert at Javascript, but I have been reading Mark Pilgrim's "Dive into HTML5" webpage and he mentioned something that I would like a better understanding of.

He states:

> Finally, you use the double-negative trick to force the result to a Boolean value (true or false).

function supports_canvas() {
  return !!document.createElement('canvas').getContext;
}

If anyone can explain this a little better I would appreciate it!

Javascript Solutions


Solution 1 - Javascript

A logical NOT operator ! converts a value to a boolean that is the opposite of its logical value.

The second ! converts the previous boolean result back to the boolean representation of its original logical value.

From these docs for the Logical NOT operator:

>Returns false if its single operand can be converted to true; otherwise, returns true.

So if getContext gives you a "falsey" value, the !! will make it return the boolean value false. Otherwise it will return true.

The "falsey" values are:

  • false
  • NaN
  • undefined
  • null
  • "" (empty string)
  • 0

Solution 2 - Javascript

Javascript has a confusing set of rules for what is considered "true" and "false" when placed in a context where a Boolean is expected. But the logical-NOT operator, !, always produces a proper Boolean value (one of the constants true and false). By chaining two of them, the idiom !!expression produces a proper Boolean with the same truthiness as the original expression.

Why would you bother? Because it makes functions like the one you show more predictable. If it didn't have the double negative in there, it might return undefined, a Function object, or something not entirely unlike a Function object. If the caller of this function does something weird with the return value, the overall code might misbehave ("weird" here means "anything but an operation that enforces Boolean context"). The double-negative idiom prevents this.

Solution 3 - Javascript

In javascript, using the "bang" operator (!) will return true if the given value is true, 1, not null, etc. It will return false if the value is undefined, null, 0, or an empty string.

So the bang operator will always return a boolean value, but it will represent the opposite value of what you began with. If you take the result of that operation and "bang" it again, you can reverse it again, but still end up with a boolean (and not undefined, null, etc).

Using the bang twice will take a value that could have been undefined, null, etc, and make it just plain false. It will take a value that could have been 1, "true", etc. and make it just plain true.

The code could have been written:

var context = document.createElement('canvas').getContext;
var contextDoesNotExist = !context;
var contextExists = !contextDoesNotExist;
return contextExists;

Solution 4 - Javascript

Using !!variable gives you a guarantee of typecast to boolean.

To give you a simple example:

"" == false (is true)
"" === false (is false)

!!"" == false (is true)
!!"" === false (is true)

But it doesn't make sense to use if you are doing something like:

var a = ""; // or a = null; or a = undefined ...
if(!!a){
...

The if will cast it to boolean so there is no need to make the implicit double negative cast.

Solution 5 - Javascript

! casts "something"/"anything" to a boolean.

!! gives the original boolean value back (and guarantees the expression is a boolean now, regardless to what is was before)

Solution 6 - Javascript

The first ! coerces the variable to a boolean type and inverts it. The second ! inverts it again (giving you the original (correct) boolean value for whatever you are checking).

For clarity you would be better off using

return Boolean(....);

Solution 7 - Javascript

document.createElement('canvas').getContext may evaluate to either undefined or an object reference. !undefined yields true, ![some_object] yields false. This is almost what we need, just inverted. So !! serves to convert undefined to false and an object reference to true.

Solution 8 - Javascript

It's to do with JavaScript's weak typing. document.createElement('canvas').getContext is a function object. By prepending a single ! it evaluates it as a boolean expression and flips the answer around. By prepending another !, it flips the answer back. The end result is that the function evaluates it as a boolean expression, but returns an actual boolean result rather than the function object itself. Prepending !! is a quick and dirty way to typecast an expression to a boolean type.

Solution 9 - Javascript

If document.createElement('canvas').getContext isn't undefined or null, it will return true. Otherwise it will return false.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionProfessionalAmateurView Question on Stackoverflow
Solution 1 - Javascriptuser113716View Answer on Stackoverflow
Solution 2 - JavascriptzwolView Answer on Stackoverflow
Solution 3 - JavascriptStriplingWarriorView Answer on Stackoverflow
Solution 4 - JavascriptfmsfView Answer on Stackoverflow
Solution 5 - JavascriptschnaaderView Answer on Stackoverflow
Solution 6 - JavascriptjasonbarView Answer on Stackoverflow
Solution 7 - Javascript9000View Answer on Stackoverflow
Solution 8 - JavascriptJimView Answer on Stackoverflow
Solution 9 - Javascriptnyuszika7hView Answer on Stackoverflow