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).
Related
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.
This question already has answers here:
+!! operator in an if statement
(6 answers)
Closed 7 years ago.
Consider the following codes
var value = 0;
for (var i=0; i < arguments.length; i++) {
value += +!!arguments[i];
}
What does +!! really do here? Is it one good programming style in JavaScript?
!!arguments[i] is a common idiom, which applies the logical negation twice, to convert the expression arguments[i] to a real boolean value.
For example,
console.log(!!{});
// true
Why we need two logical negations here? Because, it doesn't change the parity of the data. For example,
if the data was originally Truthy, then !Truthy will become false and then inverting it again !false, you will get true.
if the data was originally Falsy, then !Falsy will become true and then inverting it again !true, you will get false.
The + operator at the beginning of +!!arguments[i] is to make sure to get a Number value out of the boolean, (as !!arguments[i] is guaranteed to give a boolean).
In JavaScript, when true is converted to a number you will get 1, and 0 for false.
console.log(+true);
// 1
console.log(+false);
// 0
It's not one operator, it's three: + and then ! twice.
What that does is apply ! to arguments[i], which turns truthy values false or falsy values to true, and then applies ! to make false => true and vice-versa, and then applies the unary + to convert the result to a number (true => 1, false => 0).
A falsy value is any value that coerces to false. The falsy values are 0, "", NaN, null, undefined, and of course, false. A truthy value is any other value.
So the net result is to add the count of truthy values in arguments to value.
Is it one good programming style in JavaScript?
Using !! to turn something truthy into true and something falsy into false is completely normal practice. Using the unary + to convert something to a number is also completely normal practice.
Often !! is used to convert variable to boolean type, and + to number.
In this example it is first converted to boolean then to number in this case to 1 or 0.
Variable value contains number of truthy parameters passed to function.
This question already exists:
What does `!!~` mean in javascript? [duplicate]
Closed 8 years ago.
I was reading this blog post which mentioned using:
!!~
I have no idea what this does? at first I thought it would give an error, but the code below does run:
var _sessions = [
"_SID_1",
"_SID_2",
"_SID_3",
"_SID_4"
];
if(!!~_sessions.indexOf("_SID_5")) {
console.log('found');
} else {
console.log('!found');
}
output:
node test.js
!found
~ is the bitwise not operator. It inverts the bits of its operand. ! is the logical not operator. The bitwise not operator will return 0 when applied to -1, which is what indexOf returns when the value is not found in the array. Since 0 evaluates to false, doubly negating it will simply return false (a boolean value, rather than a numeric one):
var index = _sessions.indexOf("_SID_5");
console.log(~index); // 0
console.log(!~index); // true
console.log(!!~index); //false
The bitwise not operator will return a value less than 0 for any other possible value returned by indexOf. Since any other value will evaluate to true, it's just a shorthand method (kind of... they are both the same number of characters!) of checking whether an element exists in an array, rather than explicitly comparing with -1:
if (_sessions.indexOf("_SID_5") > -1) {
// This would work the same way
}
Update
With regards to the performance of this, it appears (in Chrome at least) to be marginally slower than the more common comparison with -1 (which itself is marginally slower than a comparison with 0).
Here's a test case and here's the results:
Update 2
In fact, the code in your question can be shortened, which may have been what the author was attempting to do. You can simply remove the !!, since the ~ will always result in 0 or below (and 0 is the only value that will evaluate to false):
if (~_sessions.indexOf("_SID_5")) {
// This works too
}
However, in a slightly different situation it could make sense to add in the ! operators. If you were to store the result of the bitwise operator in a variable, it would be a numeric value. By applying the logical not operator, you get a boolean value (and applying it again ensures you get the correct boolean value). If for some reason you require a boolean value over a numeric one, it makes a little bit more sense (but you can still just use the normal comparison with -1 or 0):
var inArray = !!~_sessions.indexOf("_SID_5");
console.log(typeof inArray); // boolean
Donald Knuth: "[...] premature optimization is the root of all evil"
For the sake of readability: please use
.indexOf !== -1
This explains it well:
The tilde operator in Javascript
Mixing the two NOT operators together can produce some interesting results:
!~(-2) = false
!~(-1) = true
!~(0) = false
!~(1) = false
!~(2) = false
So this just checks if the value equals -1 or not, and indexOf returns -1 if it does not find a match
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.
This question already exists:
Closed 13 years ago.
Possible Duplicate:
What is the !! (not not) operator in JavaScript?
I've seen operator ! used like !!. For example
var filter = !!(document.body.filters);
If I'm not wrong it's equivalent var filters = typeof document.body.filters != 'undefined'?
Is it a good practice to use !!?
It's up to you. All !! does is "cast" its argument to a Boolean.
It's a common way to convert any return type to boolean (usually to avoid compilation warnings).
And second: no, checking if type is "undefined" is mandatory anyway and "!!" can not cover it.
! negates the result of whatever is on the right. So !! negates the negated value thus ending with whatever was originally on the right.
edit: the above is true if you have boolean values, results may vary for other types ...
edit2 to elaborate some more: !! is a "type cast" operator of sorts. if you have a boolean value on the right then nothing will happen. If you have something other then a boolean value on the right, then the first ! will convert whatever is on the right to the boolean "version" of that value, and the second ! will negate that value.
Kinda like saying: return the true value of a non boolean value.
Hope that makes sense :)
var filter = !!(document.body.filters);
is NOT equivalent to
var filters = typeof document.body.filters != 'undefined'
!! merely checks if the operand is "truthy", i.e. whether it evaluates to true when used in a boolean expression. It has no relation to typeof. In general with host objects (such as document.body.filters) you are best off using typeof checks. The following article is good reading on this subject: http://peter.michaux.ca/articles/feature-detection-state-of-the-art-browser-scripting
And what if it is a string with value "undefined"?
I think !!(expression) is neat.