Can someone explain this 'double negative' trick? [duplicate] - javascript

This question already has answers here:
What is the !! (not not) operator in JavaScript?
(42 answers)
Closed 8 years ago.
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!

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

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.

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;

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.

! 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)

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(....);

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.

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.

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

Related

Difference between !! vs direct check on value

What will be difference when we check a value with !! or without it.
Example:-
a) if(!!Value) { do this } => I know this condition will return a boolean
b) if(Value) { do this } ==> This will check if value has anything inside it
But what will be difference in their usage? If not above case, in what case they both will make a difference ?
There is no difference using if(value) or if(!!value) in JavaScript or in TypeScript.
!! will coerce any following value to Boolean type.
However, an expression inside a if will be coerced to Boolean by JavaScript / TypeScript anyway.
In JavaScript the values that will be coerced to false ("falsy values") are false, 0, "", NaN, null, undefined.
Any other is truthy (including empty arrays and objects), i.e. will be coerced to true.

! operator in Javascript - use cases

I'm just starting to learn Javascript, and am using this reference: https://www.discovermeteor.com/blog/javascript-for-meteor/
There's an interesting commentary that I can't get my head around. I quote below.
An interesting consequence of the ! operator is that it always returns a boolean value, even if what comes after is not a boolean:
a = 12;
!a; // false
This means that if you want to convert a variable to boolean you can just use the ! operator twice (once to force the variable to boolean, a second time to revert the value back):
a = 12;
!!a; // true
Or:
a = 0;
!!a; // false
Can anyone help me makes sense of the wording?
Is it simply trying to say that any integer other than 0 gets assigned a Boolean value of True, and that you can return a Boolean value of True/False by using "!" and "!!" respectively?
Yes, !!something is a way to convert something into a boolean (essentially finding out whether something is truthy). 0 and NaN are the only number values that would convert to false with the !! operator (or Boolean() call). All other numbers will be true.
Similarly, +something is a way to convert something into a number.
I usually prefer the more explicit approach: Boolean(something) and Number(something).

Why does an assignment in an if statement equate to true?

Let me start off by saying I understand the difference between =, ==, and
===. The first is used to assign the right-hand value to the left-hand variable, the second is used to compare the equivalency of the two values, and the third is used not just for equivalency but type comparison as well (ie true === 1 would return false).
So I know that almost any time you see if (... = ...), there's a pretty good chance the author meant to use ==.
That said, I don't entirely understand what's happening with these scripts:
var a = 5;
if (a = 6)
console.log("doop");
if (true == 2)
console.log('doop');
According to this Javascript type equivalency table, true is equivalent to 1 but not 0 or -1. Therefore it makes sense to me that that second script does not output anything (at least, it isn't in my Chrome v58.0.3029.110).
So why does the first script output to the console but the second doesn't? What is being evaluated by the first script's if statement?
I dug into my C# knowledge to help me understand, but in C# you cannot compile if (a = 5) Console.WriteLine("doop"); so I had to explicitly cast it to a bool by doing if (Convert.ToBoolean(a = 5)) but then that makes sense it would evaluate to true because according to MSDN's documentation, Convert.ToBool returns true if the value supplied is anything other than 0. So this didn't help me very much, because in JS only 1 and true are equal.
There's a difference between making an abstract equality comparison with == and performing a simple type cast to boolean from a number value. In a == comparison between a boolean and a number, the boolean value is converted to 0 or 1 before the comparison. Thus in
if (true == 2)
the value true is first converted to 1 and then compared to 2.
In a type cast situation like
if (x = 2)
the number is converted to boolean such that any non-zero value is true. That is, the value 2 is assigned to x and the value of the overall expression is 2. That is then tested as boolean as part of the evaluation of the if statement, and so is converted as true, since 2 is not 0.
The various values that evaluate to boolean false are 0, NaN, "", null, undefined, and of course false. Any other value is true when tested as a boolean (for example in an if expression).
Why does an assignment in an if statement equate to true?
It doesn't. An assignment is evaluated as whatever value is assigned.
This expression is a true value:
a = true
But this expression is a false value:
b = false
That's true whether or not you put it in an if statement or not.

Confusion about relationship between Boolean value "true" and string

if(true){
alert("hello");
}
if("string"){
alert("hello");
}
The code above shows that a string can be used as a substitute for Boolean value "true". Why does this work and does this mean that Boolean value "true" and string have the same data type?
A string as a statement, represents it's existence, in other words, if the string is set, it will return true, as if its "" it will return as false
This way you can check a variable if it is set or not
JavaScript's conditional operators such as if-else and a ? b : c don't require the condition to be of actual Boolean type but rather check whether it is truthy or a falsy value in JavaScript terms.
For example, such values as null and 0 are considered falsy so they would be treated like false in if-else and ternary operators.
In a broader sense this might be considered as a case of type coercion, see for example this question for more information. So when an interpreter sees non-boolean expression inside an if it is "re-writing" it like if (Boolean("string")) { ... }, i.e. invoking conversion from the expression to the exact boolean type.
if("string"){
alert("hello");
}
since you did not include an operator, as default, it just checks for the existence of the string, "string" == true.
JavaScript has a boolean type, with possible values true and false (both of which are keywords.) Any value can be converted to a boolean according to the following rules:
false, 0, empty strings (""), NaN, null, and undefined all become false.
All other values become true.
You can perform this conversion explicitly using the Boolean() function:
Boolean(""); // false
Boolean(234); // true
https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript

When to use the double not (!!) operator in JavaScript

I understand what the double not operator does in JavaScript. I'm curious about it's use though and whether or not a recent assertion that I made is correct.
I said that if (!!someVar) is never meaningful nor is (!!someVar && ... because both the if and the && will cause someVar to be evaluated as a boolean so the !! is superfluous.
In fact, the only time that I could think of that it would be legitimate to use the double not operator is if you wanted to do a strict comparison to another boolean value (so maybe in return value that expects true or false explicitly).
Is this correct? I started to doubt myself when I noticed jQuery 1.3.2 used both if (!!someVar) and return !!someVar && ...
Does the double not have any actual effect in these situations?
My personal opinion is that it just leads to confusion. If I see an if statement, I know it's evaluating it as a boolean.
In the context of if statements I'm with you, it is completely safe because internally, the ToBoolean operation will be executed on the condition expression (see Step 3 on the spec).
But if you want to, lets say, return a boolean value from a function, you should ensure that the result will be actually boolean, for example:
function isFoo () {
return 0 && true;
}
console.log(isFoo()); // will show zero
typeof isFoo() == "number";
In conclusion, the Boolean Logical Operators can return an operand, and not a Boolean result necessarily:
The Logical AND operator (&&), will return the value of the second operand if the first is truly:
true && "foo"; // "foo"
And it will return the value of the first operand if it is by itself falsy:
NaN && "anything"; // NaN
0 && "anything"; // 0
On the other hand, the Logical OR operator (||) will return the value of the second operand, if the first one is falsy:
false || "bar"; // "bar"
And it will return the value of the first operand if it is by itself non-falsy:
"foo" || "anything"; // "foo"
Maybe it's worth mentioning that the falsy values are: null, undefined, NaN, 0, zero-length string, and of course false.
Anything else (that is not falsy, a Boolean object or a Boolean value), evaluated in boolean context, will return true.
Yes, !!var is used when you want 0||1 return value.
One is simple comparison of bool values, when you want "a == b" be equivalent of "a xor not b" except a=5 and b=7 would both be true but not be equal.
Another is when you want to coerce a set of conditions into bits of a variable:
var BIT_NONEMPTY=1;
var BIT_HASERRORS=2;
var BIT_HASCHILDREN=4;
var BIT_HASCONTENT=8;
result_bitfields =
(!!countLines())*BIT_NOTEMPTY +
(!!errorCode())*BIT_HASERRORS +
(!!firstChild())*BIT_HASCHILDREN +
(!!getContent())*BIT_HASCONTENT;
Not very useful in Javascript which lives pretty far from bit values, but may be useful at times.

Categories