I am wondering why the Boolean coercion fails in this case:
!!(new Boolean(false)) === true
Although:
(new Boolean(false).valueOf()) === false
Mozilla says:
Booleans are returned as-is.
I am wondering what "as-is" means in the context of a coercion. I thought "coercion" means "convert anything to a primitive boolean". How is it possible that something which is meant to be false gets coerced to true?
BTW: Consequently this fails too:
Boolean(new Boolean(false)) === true
It seems to me, that the Boolean class itself is an error. Maybe I have to use the following code:
if (arg instanceof Boolean)
throw new Error("Stop doing nonsense")
Or maybe this:
function coerce_boolean_correctly (arg) {
if (arg instanceof Boolean)
return coerce_boolean_correctly(arg.valueOf())
return !!arg
}
There is a huge difference between a Boolean object and a Boolean primitive. The MDN page you referenced, actually warns about this at the very outset:
Do not confuse the primitive Boolean values true and false with the true and false values of the Boolean object.
Any object, including a Boolean object whose value is false, evaluates to true when passed to a conditional statement.
And this (what I marked in bold) is exactly what happens in your code: it creates a new Boolean(false) and that will coerce to true -- in other words it is a truthy value. In your code you have explicitly converted it to a boolean primitive, by applying ! to it twice. In either case (implicit coercion or explicit conversion) new Boolean(false) is truthy. Fact is that all objects are considered truthy (when coerced to boolean, they evaluate to true).
The article continues with:
Do not use the Boolean() constructor with new to convert a non-boolean value to a boolean value — use Boolean as a function or a double NOT instead.
This suggests that your code should be modified to drop the use of new, and call Boolean as a plain function, not as constructor:
!!(Boolean(false)) === false
When Boolean is called as plain function, it returns a primitive boolean (false or true). But anything that is called as constructor, even Boolean, will return an object. And objects are truthy.
When in the context of coercion MDN states "Booleans are returned as-is." they refer to boolean primitives. (Boolean) objects are covered by the last bullet point in the same list: "All objects become true". The latter in includes Boolean objects.
A Boolean object has a valueOf method which returns a boolean primitive, and so it returns what you would intuitively expect.
The MDN article rightly says:
Warning: You should rarely find yourself using Boolean as a constructor.
Don't use new Boolean, but Boolean.
If for some reason you have a Boolean object, really ask yourself why you have that object in the first place. Tackle the code that created that object and use a primitive boolean from the outset.
Objects are truthy
Some are surprised in a similar way that the following holds:
if (!!new String("")) console.log("An empty string is truthy!?");
if (!!new Number(0)) console.log("The number 0 is truthy!?");
if (!!new Number(NaN)) console.log("NaN is truthy!?");
if (!!new Object(null)) console.log("null is truthy!?");
if (!!new Object(undefined)) console.log("Undefined is truthy!?");
It is the same principle: objects are truthy. Always.* No matter what their constructor is named. No matter what value was passed to that constructor.
* document.all is an abhorrent, but accepted, violation of this rule.
See also
What's the point of the Boolean object?
What is the purpose of new Boolean() in Javascript?
Related
I just learned there are truthy and falsy values in python which are different from the normal True and False.
Can someone please explain in depth what truthy and falsy values are? Where should I use them? What is the difference between truthy and True values and falsy and False values?
We use "truthy" and "falsy" to differentiate from the bool values True and False. A "truthy" value will satisfy the check performed by if or while statements. As explained in the documentation, all values are considered "truthy" except for the following, which are "falsy":
None
False
Numbers that are numerically equal to zero, including:
0
0.0
0j
decimal.Decimal(0)
fraction.Fraction(0, 1)
Empty sequences and collections, including:
[] - an empty list
{} - an empty dict
() - an empty tuple
set() - an empty set
'' - an empty str
b'' - an empty bytes
bytearray(b'') - an empty bytearray
memoryview(b'') - an empty memoryview
an empty range, like range(0)
objects for which
obj.__bool__() returns False
obj.__len__() returns 0, given that obj.__bool__ is undefined
As the comments described, it just refers to values which are evaluated to True or False.
For instance, to see if a list is not empty, instead of checking like this:
if len(my_list) != 0:
print("Not empty!")
You can simply do this:
if my_list:
print("Not empty!")
This is because some values, such as empty lists, are considered False when evaluated for a boolean value. Non-empty lists are True.
Similarly for the integer 0, the empty string "", and so on, for False, and non-zero integers, non-empty strings, and so on, for True.
The idea of terms like "truthy" and "falsy" simply refer to those values which are considered True in cases like those described above, and those which are considered False.
For example, an empty list ([]) is considered "falsy", and a non-empty list (for example, [1]) is considered "truthy".
See also this section of the documentation.
Python determines the truthiness by applying bool() to the type, which returns True or False which is used in an expression like if or while.
Here is an example for a custom class Vector2dand it's instance returning False when the magnitude (lenght of a vector) is 0, otherwise True.
import math
class Vector2d(object):
def __init__(self, x, y):
self.x = float(x)
self.y = float(y)
def __abs__(self):
return math.hypot(self.x, self.y)
def __bool__(self):
return bool(abs(self))
a = Vector2d(0,0)
print(bool(a)) #False
b = Vector2d(10,0)
print(bool(b)) #True
Note: If we wouldn't have defined __bool__ it would always return True, as instances of a user-defined class are considered truthy by default.
Example from the book: "Fluent in Python, clear, concise and effective programming"
Truthy values refer to the objects used in a boolean context and not so much the boolean value that returns true or false.Take these as an example:
>>> bool([])
False
>>> bool([1])
True
>>> bool('')
False
>>> bool('hello')
True
Where should you use Truthy or Falsy values ?
These are syntactic sugar, so you can always avoid them, but using them can make your code more readable and make you more efficient.
Moreover, you will find them in many code examples, whether in python or not, because it is considered good practice.
As mentioned in the other answers, you can use them in if tests and while loops. Here are two other examples in python 3 with default values combined with or, s being a string variable. You will extend to similar situations as well.
Without truthy
if len(s) > 0:
print(s)
else:
print('Default value')
with truthy it is more concise:
print(s or 'Default value')
In python 3.8, we can take advantage of the assignment expression :=
without truthy
if len(s) == 0:
s = 'Default value'
do_something(s)
with truthy it is shorter too
s or (s := 'Default value')
do_something(s)
or even shorter,
do_something(s or (s := 'Default value'))
Without the assignment expression, one can do
s = s or 'Default value'
do_something(s)
but not shorter. Some people find the s =... line unsatisfactory because it corresponds to
if len(s)>0:
s = s # HERE is an extra useless assignment
else:
s = "Default value"
nevertheless you can adhere to this coding style if you feel comfortable with it.
Any object in Python can be tested for its truth value. It can be used in an if or while condition or as operand of the Boolean operations.
The following values are considered False:
None
False
zero of any numeric type, for example, 0, 0L, 0.0, 0j.
any empty sequence, for example, '', (), [].
any empty mapping, for example, {}.
instances of user-defined classes, if the class defines a __nonzero__() or __len__() method, when that method returns the integer zero or bool value False.
All other values are considered True -- thus objects of many types are always true.
Operations and built-in functions that have a Boolean result always return 0 or False for false and 1 or True for true, unless otherwise stated.
In case of if (!id) {}
!expr returns false if its single operand can be converted to true; otherwise, returns true.
If a value can be converted to true, the value is so-called truthy. If a value can be converted to false, the value is so-called falsy.
Examples of expressions that can be converted to false are:
null;
NaN;
0;
empty string ("" or '' or ``);
undefined.
Even though the ! operator can be used with operands that are not Boolean values, it can still be considered a boolean operator since its return value can always be converted to a boolean primitive. To explicitly convert its return value (or any expression in general) to the corresponding boolean value, use a double NOT operator or the Boolean constructor.
Example:
n1 = !null // !t returns true
n2 = !NaN // !f returns true
n3 = !'' // !f returns true
n4 = !'Cat' // !t returns false
While in case of if (id != null) {} it will only check if the value in id is not equal to null
reference https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_NOT
Falsy means something empty like empty list,tuple, as any datatype having empty values or None.
Truthy means :
Except are Truthy
Why does comparing an explicitly called String constructor to an implicit string evaluate true, but adding the new keyword makes it evaluate false on deep equals, but true again on shallow equals?
> "hello"===String("hello")
true
> "hello"==new String("hello")
true
> "hello"===new String("hello")
false
Edit: after further testing, this appears to happen with all types that have implicit constructors.
Edit 2: to clarify, this is not a question of == vs. ===, but one of implicit vs. explicit constructors.
When you use the new keyword you are creating an object. If you were to check the typeof new String('hello') you will see that it is of type object. Checking the type of 'hello' on its own will yield string.
As you may know, using a strict equals operator (===) will check for both value and type, so it will return false due to the types not matching.
The reason the expression without the new keyword returns true is because calling upon the String global object is not the same as calling the constructor using new:
String literals (denoted by double or single quotes) and strings returned from String calls in a non-constructor context (i.e., without using the new keyword) are primitive strings.
As such, the type of the return value will be string and not object, so the strict check will return true.
The difference between == and === is that === requires the type to be the same, while == does not.
So this is telling you that both "hello" and String("hello") are of the same type (which is string); but new String("hello"), while it has the same value, is a different type (which is object)
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').
+true // result: 1
true.valueOf() // result: true
+true === true.valueOf() // result: false
In Javascript Type Coersion, the function called for evaluation is valueOf(). But if the function is called explicity it returns a different value.
Type Coersion in Javascript happens if == is used, which is kinda loose comparison operator.
=== is strict comparison operator which doesn't coerce the types when comparing so it remains an integer and the other one bool
+true === true.valeOf() // false
+true == true.valueOf() // true
Docs:
The identity (===) operator behaves identically to the equality (==)
operator except no type conversion is done, and the types must be the
same to be considered equal.
Why true.valueOf() doesn't returns 1
The answer is true.valueOf returns true, which is the primitive value of a Boolean object. Also the quote is from MDN
The valueOf method of Boolean returns the primitive value of a Boolean
object or literal Boolean as a Boolean data type.
What does +true do:
+true is same as Number(true) and it is a well known fact that 0 is false and 1 is true in almost every language. In fact in C++ they are used as booleans.
the function called for evaluation is valueOf()
Not always. valueOf() is only meaningful for non-primitive types, since it is defined to return the primitive value of the given object. true by itself is a Boolean primitive and as such calling true.valueOf() would be completely redundant.
The unary + and - sign operators always return a number by definition. Since a Boolean quite conveniently converts to a number, it only makes sense that +true returns 1.
There is no reason +true and true.valueOf() should both correspond to the same value.
for strict comparison you should do like this:
Number(true.valueOf()) === +true
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.