I've come across this javascript code in the wild and am having trouble understanding exactly what it does and how it works:
// Ensure its bool.
options.something = (!(options.something === false));
From what I can tell, options.something is just being set to the opposite of false. Is there any functional difference between the above and just doing the following instead?
options.something = true;
JSHint and JSLint appropriately give a "confusing use of '!'" warning on the original code.
Interesting piece of code. The only way options.something will be assigned false is if it is itself false.
Let's break it down:
(!(options.something === false)) =>
(!(false === false)) =>
(!true) =>
false
So, at then end of the day the code ensures that options.something is either true or false, and the only way it can be false is if it actually is the value false (not undefined, null, 0, etc.).
On the other hand, it will be the value true if it begins as anything else (such as undefined, null, 0, etc.).
It's not actually a toggle, it's a check that the value is a boolean.
Read it from the inside out.
Inner parenthesis asks if something is false. If it is the value of the expression is true (false does equal false). Take the negative of that (! true) which returns the boolean value false.
If something is true, the inner expression is false, true != false. Take the negative of that (! false) and the result is true.
OK, so what if something is undefined? Undefined will evaluate as false and since false === false the expression is true. Negating that (! true) returns false.
So anything that is true is returned as true and undefined or false values always return false.
Related
Im trying to understand why comparing standard functions always returns a Boolean false
Like for the isNaN function
>isNaN === true
false
>isNaN === false
false
But
>Boolean(isNaN)
true
Now to make things a little more interesting
>!isNaN === false
true
>!isNaN === true
false
This occurs with standard function like Number, Object etc.
Does anyone know what happens under the hood in JavaScript ?
I recommend you read truthy and falsy values, in short, isNaN is a function, it actually exists, so you can use it as a short hand for true checking, very useful for everyday programming.
When you use === type checking is done, and then a bool != a function.
When you pre-pend ! to it, you are actually casting to boolean type and reversing the value to true so that is why the comparison changes.
Here are the lists of Truthy and Falsy values.
isNaN is truthy because it's a function.
>isNaN === true
false
>isNaN === false
false
Because isNaN is a function.
>Boolean(isNaN)
true
Because again, isNaN is a function and functions are truthy values. Please refer following to see output specs for Boolean
NaN is one of those vestigial implementations of questionable origins, but for the most part I get it. However, I typed this into a Node prompt today and couldn't really make sense of it...
NaN = !NaN
> true
Is this simply returning the evaluated result of !NaN? This makes sense, but I'm surprised that there's not an error when attempting to assign NaN to another value.
Note: this question is about this specific syntax structure; there are a lot of questions related to NaN and isNaN out there but I couldn't find an answer after googling. Thanks to Ori Drori for the best answer thus far.
console.log(NaN = !NaN);
You are assigning true to NaN instead of comparing NaN to !NaN using === or ==, so the operation returns the assigned value -> true. Javascript ignores this assignment silently because NaN is read only.
console.log(NaN = true);
// NaN hasn't changed
console.log(NaN);
If you'll add use strict to your code, JS will throw a read only error instead:
'use strict';
NaN = true;
= is the asignment operator.
== and === are comparison operators.
NaN == !NaN
false
NaN === !NaN
false
Perhaps more surprisingly:
NaN == NaN
false
NaN === NaN
false
For more about NaN: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/NaN
Try running Javascript in a strict mode to avoid most of the problems.
NaN, null, false, "", null, undefined, 0 etc they are considered as falsy values (remember falsy !== false) in javascript, no matter you use a strict mode or not.
// 'use strict';
console.log(!NaN); // true
console.log(!null); // true
console.log(!false); // true
console.log(!""); // true
console.log(!null); // true
console.log(!undefined); // true
console.log(!0); // true
It is true in Python as well, except for NaN. For example,
print(not False) # True
print(not None) # True
print(not float("NaN")) # False
print(not "") # True
print(not 0) # True
Source of confusion
When we use multiple languages sometimes it can be a source of confusion.
For example,
In Python 'cat' in ['fat', 'cat', 'rat', 'hat'] returns True.
In Javascript 'cat' in ['fat', 'cat', 'rat', 'hat'] (exactly the same piece of code) returns false no matter you use a strict mode or not.
In Python print(not []) returns True.
In Javascript console.log(![]); returns false.
This is one of the reasons why I always love to use debuggers, REPL etc no matter how simple the code is.
Using = operator, you assign the value to a variable. However, what you don't know is by doing that, it returns the value of what is being assigned. Typing:
v = 1
in a JavaScript REPL will display 1, because that is what was assigned to v. So, doing:
NaN = !NaN
Will assign the opposite value of NaN to NaN itself. Since NaN in boolean is false, then !NaN in boolean must be true.
Javascript is really weird: When you write
NaN = true // true
which you basically do in your statement, you get "true". This is the same behavior as when you write
a = true // true
where the right side of the assignment is returned. But if you add var and write
var a = true // undefined
then nothing is returned. Also if you replace NaN with an expression that evaluates to NaN, for example
1/"a" = true // error!
then you get a ReferenceError. I recommend to never use the return values of assignments. The behavior is inconclusive and your code will be hard to read. You can enable "strict mode" to check this for you.
It may be that I'm just very groggy this morning, but I'm having trouble understanding why this returns as true:
_.some([null, 0, 'yes', false]); // true
I know that _.some() returns true if at least one of the elements passes the predicate test as true. But from my understanding, if no predicate is provided, _.identity() is used. But console.log-ing each of those elements individually with _.identity() didn't return true for any of them. So why does it return true?
Without a predicate, some uses identity, which uses the value itself, and 'yes' is truthy.
A quick dive through the annotated source (paying special attention to cb and the handling of missing predicates there) leaves you with, essentially, a coercion to boolean when they do:
if (predicate(obj[currentKey], currentKey, obj)) return true;
No predicate means you're working with the original value there, so if ('yes'), which is true.
You're not seeing true in the console for any of those values because _.identity will return the value itself (so 'yes') rather than coercing it to a boolean. If you were to do !!'yes' (coercion and double-not), you will see true.
'yes' is truthy:
_.some([null]) // false
_.some([0]) // false
_.some(['yes']) // true
_.some([false]) // false
From the Truth, equality in javascript link:
The construct if ( Expression ) Statement will coerce the result of evaluating the Expression to a boolean using the abstract method ToBoolean for which the ES5 spec defines the following algorithm:
string: The result is false if the argument is the empty String (its length is zero); otherwise the result is true.
It doesn't need to return the literal value true, it only needs to return a truthy value (although you always should return only booleans).
The non-empty string 'yes' is truthy (you can test by Boolean('yes') or !!'yes').
I understand that
if( value ) {
}
will evaluate to true if value IS NOT null, undefined, NaN, empty string (""), 0, or false
But, does
if (! value ) {}
evaluate to true if the value IS null, undefined, NaN, empty string (""), 0, or false ?
I am using Google Scripts and I am taking data from a spreadsheet in which some cells are blank. For those cells I want to be sure the value returns as "empty string" rather than any of the other possibilities like, undefined, for example (some are currently returning 'undefined' which is what led me to seek this answer).
I would like to use this code, as long as it does what I think it does:
if (! value ) {value = ""}
(P.S. I started at this thread: Is there a standard function to check for null, undefined, or blank variables in JavaScript?, but the answers do not address the opposite scenario)
In short, yes.
Coerce or cast the value to boolean by using the negative ! and double negative !! which will turn all falsey values to false and all other values to true, then just check wether its true or false knowing they're boolean.
So, in other words, if you want the boolean of the opposite, just prepend ! if you want the boolean of the actual value, prepend !!
!"" === true; //inverted
!!"" === false;//actual
Yes, those will evaluate to true:
if(!NaN){console.log('true!');}
true!
if(!undefined){console.log('true!');}
true!
if(!null){console.log('true!');}
true!
if(!''){console.log('true!');}
true!
if(!0){console.log('true!');}
true!
I was wondering when the Javascript if expression actually evaluates to false and when to true. When is the if statement false, and is that true for all JS interpreters?
I guess the condition is false on
false
undefined
null
0
otherwise true. Is that correct for all implementations (tested in Safari/WebKit console), or am I better off with explicit checking like (typeof a === "undefined")?
The following values will evaluate to false:
false
undefined
null
0
NaN
the empty string ("")
https://developer.mozilla.org/en/JavaScript/Guide/Statements#if...else_Statement
If you want to check for variable existence, and a is not declared anywhere in your script, typeof a === 'undefined' is the way, or you can use if (!window.a). Otherwise a ReferenceError is thrown.
Your guessing seems to be correct. An empty string and NaN also evaluate to false (or, as some like it falsy). The fact that 0 evaluates to false may be tricky, but it's handy too, in statements like while (i--) (if i has the value of 0 it evaluates to false and the while loop stops).