I use Chrome browser 60.x, and test the code isNaN([3]).
The result is false, but I cannot understand it.
[3] is an Array, and it is not empty.
I think [3] is array object, and it is not an number.
Otherwise the result of isNaN(["ABC"]) is true.
And another result of isNaN([1,2,3]) is true.
So I guess javascript engine is force changing array to number which the array has a single element.
Please let me know what is happened isNaN function for array parameter.
ref1: Why is isNaN(null) == false in JS?
ref2: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isNaN
[EDIT] Thank you everyone for answering.
I understand javascript parsed the value implicitly before comparison.
And I found a useful link while reading Nina Scholz's answer.
The comparison table : http://dorey.github.io/JavaScript-Equality-Table/
When you use isNaN it tries to parse your input value into the number and then checks if it is NaN or not.
See some examples.
For an array with one item, the Number() function returns an object, which actually hold the first item as a value (see console.log). For many items it returns NaN, so you get isNaN's result -> true.
const a = new Number([3]);
console.log(`a is ${a}`);
console.log(`isNaN(a) - ${isNaN(a)}`);
const b = new Number([3,4,5]);
console.log(`b is ${b}`);
console.log(`isNaN(b) - ${isNaN(b)}`);
According to the rules for equality comparisons and sameness, the array is converted, first with toString and then to a number for checking.
console.log(isNaN([3]));
console.log(isNaN('3')); // convert with toString to a primitive
console.log(isNaN(3)); // convert to number
Javascript works in the following way: It tries to convert the object to integer if the argument of the function is expected to be an integer. For example running
x = increment([3])
will result in x = 4. Therefore running
isNan([3])
will result in false, since [3] gets converted to 3 and 3 is a number. Similarly, ["ABC"] cannot get converted to integer, therefore isNaN(["ABC"]) = true. Also, javascript fails to convert [1,2,3] to a number, since there are three numbers in array, therefore
isNaN([1,2,3]) = true
Because, as a shorthand in Javascript,, arrays containing only one number are considered castable to the number it contains. You can see this behavior with ==
3 == [3] // returns true
Additionaly, that's also why [0] is a falsy value, whereas [n] with n not zero is a truthy value, an horrible potential source of bugs.
[0] == false // returns true
[1] == false // returns false
So as we know
isNaN([3]) // returns false
A workaround to test number vs array with number
Number([3]) === [3] //returns false
Number(3) === 3 // returns true
Remember that === means matching the values and type
Related
I was encountering a lot of bugs in my code because I expected this expression:
Boolean([]); to evaluate to false.
But this wasn't the case as it evaluated to true.
Therefore, functions that possibly returned [] like this:
// Where myCollection possibly returned [ obj1, obj2, obj3] or []
if(myCollection)
{
// ...
}else
{
// ...
}
did not do expected things.
Am I mistaken in assuming that [] an empty array?
Also, Is this behavior consistent in all browsers? Or are there any gotchas there too? I observed this behavior in Goolgle Chrome by the way.
From http://www.sitepoint.com/javascript-truthy-falsy/
The following values are always falsy:
false
0 (zero)
0n (BigInt zero)
"" (empty string)
null
undefined
NaN (a special Number value meaning Not-a-Number!)
All other values are truthy, including "0" (zero in quotes), "false" (false in quotes), empty functions, empty arrays ([]), and empty objects ({}).
Regarding why this is so, I suspect it's because JavaScript arrays are just a particular type of object. Treating arrays specially would require extra overhead to test Array.isArray(). Also, it would probably be confusing if true arrays behaved differently from other array-like objects in this context, while making all array-like objects behave the same would be even more expensive.
You should be checking the .length of that array to see if it contains any elements.
if (myCollection) // always true
if (myCollection.length) // always true when array has elements
if (myCollection.length === 0) // same as is_empty(myCollection)
While [] equals false, it evaluates to true.
yes, this sounds bad or at least a bit confusing. Take a look at this:
const arr = [];
if (arr) console.log("[] is truethy");
if (arr == false) console.log("however, [] == false");
In practice, if you want to check if something is empty,
then check the length. (The ?. operator makes sure that also null is covered.)
const arr = []; // or null;
if (!arr?.length) console.log("empty or null")
[]==false // returns true
This evaluates to true, because of the Abstract Equality Algorithm as mentioned here in the ECMA Specification #Section 11.9.3
If you run through algorithm, mentioned above.
In first iteration, the condition satisfied is,
Step 7: If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
Hence the above condition transforms to -> [] == 0
Now in second iteration, the condition satisfied on [] == 0:
Step 9: If Type(x) is Object and Type(y) is either String or Number, return the result of the comparison ToPrimitive(x) == y.
[] is an object, henceforth, on converting to primitive, it transforms to an empty string ''
Hence, the above condition transforms to -> '' == 0
In third iteration, condition satisfied, is:
Step 5: If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x) == y.
As we know, empty string, '' is a falsy value, hence transforming an empty string to number will return us a value 0.
Henceforth, our condition, will transform to -> 0 == 0
In fourth iteration, the first condition is satisfied, where the types are equal and the numbers are equal.
Henceforth, the final value of the [] == false reduces to 0 == 0 which is true.
Hope this answers your question. Otherwise, you can also refer this youtube video
I suspect it has something to do with discrete math and the way a conditional (if then) works. A conditional has two parts, but in the instance where the first part doesn't exist, regardless of the second part, it returns something called a vacuous truth.
Here is the example stated in the wikipedia page for vacuous truths
"The statement "all cell phones in the room are turned off" will be true when no cell phones are in the room. In this case, the statement "all cell phones in the room are turned on" would also be vacuously true"
The wikipedia even makes specific mention of JavaScript a little later.
https://en.wikipedia.org/wiki/Vacuous_truth#:~:text=In%20mathematics%20and%20logic%2C%20a,the%20antecedent%20cannot%20be%20satisfied.&text=One%20example%20of%20such%20a,Eiffel%20Tower%20is%20in%20Bolivia%22.
Also want to add, that all objects in JavaScript (arrays are objects too) are stored in memory as links and these links are always not null or zero, that's why Boolean({}) === true, Boolean([]) === true.
Also this is the reason why same objects (copied by value not the link) are always not equal.
{} == {} // false
let a = {};
let b = a; // copying by link
b == a // true
As in JavaScript, everything is an object so for falsy and empty, I use the below condition:
if(value && Object.keys(value).length){
// Not falsy and not empty
}
else{
// falsy or empty array/object
}
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
When I run this in node I get the following result. Why?
//Why does this code return the results that it does?
function isBig(thing) {
if (thing == 0 || thing == 1 || thing == 2) {
return false
}
return true
}
isBig(1) // false
isBig([2]) // false
isBig([3]) // true
The == operator in JavaScript converts its operands into a common type before checking for equality (that's why it is recommended always to use the === operator, which respects the types).
In your case the common type is number, so the each given array is converted into a number. For a single element array the conversion into a number results in the single element (converted to a number).
The parameter [2] equals the number 2, so return false.
[3] on the other hand does neither equal 0, 1, or 2, so return true.
See also https://www.w3schools.com/js/js_type_conversion.asp for more examples.
== compares equity loosely.
To quote developer.mozilla.org
Loose equality compares two values for equality, after converting both values to a common type.
This means that [2] == 2 is true it also means "2" == 2 is true
and it's why it is so often recommended to use strict equality so that [2] === 2 is false unless you are really looking for the conversion.
To piggy back on what Mark_M said when you pass the [2] and [3] to the function it's treating them as object literals instead of numbers. Then in your function call its typecasting them for the comparison.
console.log(typeof(1));
console.log(typeof[2]);
console.log(typeof[3]);
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.
The following are examples that make sense to me.
isFinite(5) // true - makes sense to me, it is a number and it is finite
typeof 5 // "number"
isFinite(Infinity) // false - makes sense for logical reasons
typeof Infinity // "number"
isFinite(document) // false - makes sense as well, it's not even a number
typeof document // "object"
The following is where I get confused.
isFinite(null) // true - Wait what? Other non-number objects returned false. I see no reason?
typeof null // "object"
I just don't see the reasoning behind this.
What I'd like is the most low-level answer possible.
I think null is being converted to 0, why? What other impacts does this have?
The ECMAScript spec (5.1) defines isFinite to act as such:
isFinite (number)
Returns false if the argument coerces to NaN, +∞, or −∞, and otherwise returns true.
If ToNumber(number) is NaN, +∞, or −∞, return false.
Otherwise, return true.
In other words, isFinite is calling ToNumber on whatever's passed in, and then comparing it to either pos/neg infinity or NaN.
In JavaScript (note the use of != instead of the more common !==, causing the type cast):
function isFinite(someInput) {
return !isNaN(someInput) &&
someInput != Number.POSITIVE_INFINITY &&
someInput != Number.NEGATIVE_INFINITY;
}
(As noted in the comments below, someInput != NaN is not needed, as NaN is defined to not be equivalent to everything, including itself.)
Now, why is null converted to zero (as opposed to undefined)? As TylerH says in the comments, null means that a value exists, but is empty. The mathematical representation of this is 0. undefined means that there isn't a value there, so we get NaN when trying to call ToNumber on it.
http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.2.5
However, ECMAScript 6 is bringing along a non-converting isFinite as a property of Number. Douglas Crockford suggested it here: http://wiki.ecmascript.org/doku.php?id=harmony:number.isfinite
From MDN:
The global isFinite() function determines whether the passed value is
a finite number. If needed, the parameter is first converted to a
number.
So, it's converted to a number...
isFinite(null)
isFinite(+null) //convert to a number
isFinite(0) // true because +null or Number(null) = 0
The spec says that the global isFinite() method will forcibly convert the parameter to a number.
You could, however, use (at your own risk) the EcmaScript 6 spec's Number.isFinite() which doesn't perform this conversion.
Number.isFinite(null) // false
Or, like lodash and underscore do it...
var _.isFinite = function(obj) {
return isFinite(obj) && !isNaN(parseFloat(obj));
};
isFinite calls ToNumber on its argument. So
> Number(null)
0
> Number(document)
NaN
> isFinite(0)
true
> isFinite(NaN)
false
> isFinite(null)
true
> isFinite(document)
false
Because, if you say
Number(null) === 0 which is finite
See To Number Conversions
Which says that, for argument type null result is +0
isFinite typecasts it's argument to a number, if it's not already a number. Essentially you have isFinite(Number(null)) and Number(null) === 0. Which is finite.
Beside null, you find these examples interesting too:
alert(isFinite(' ')); //true
alert(isFinite('')); //true
alert(isFinite(null)); //true
alert(isFinite(!undefined)); //true
In JavaScript implicit conversion take place, This conversion try to convert bool to integer when comparing numbers with boolean, or number to string when comparing string with numbers. If you treat any data-type as number it implicitly converted to number so all above cases return zero which is finite. See Here
If you try Number(undefined) it give you a NaN on negate this would produce a 1 which is finite.