Why parseInt(key) === NaN always evaluates to false - javascript

I'm doing decision based on dictionary key, i have only two types of keys, numeric and alpha,
var _dict = { 'a':'one', 'b':'two', '1':'three' };
$.each( _dict, function( key, value ){
if( parseInt( key ) === NaN ) {
// this statement always evalute to false
} else {
}
});
if i print console.log(parseInt('a')), it will also return NaN
I alreay found the solution from this question javascript parseInt return NaN for empty string
But i was wondering why it always evaluates to false.

That's because NaN is defined to be not equal to anything (including itself). Check it:
>> NaN === NaN
False
You should use isNaN() function instead:
>> isNaN(NaN)
true
>> isNaN(0/0)
true
>> isNaN(parseInt('a'))
true

Related

Is 0 considered true in ES6?

Is 0 considered true in ES6? Or all strings considered true?
this is returning true:
var value = "0";
var isTrue = value ? true : false; // true
I thought === was for strict equality.
If it has changed is there a way to get the old way for compatibility sake?
UPDATE:
Thanks. The value I'm receiving will always be a string so I'll check for "0" and "false":
var booleanValue = value && value!=="0" && value!=="false" ? true : false;
"0" is true because it's just a string and has a value, but the 0 as a number is considered false
This is a list of all falsy values in javascript:
false
0
'' or ""
null
undefined
NaN
Only the String '' is a falsy value, meaning that it is an empty string.
'0' is a string with content so it isn't a falsy value, but 0 is one.
All strings that have characters in them are truthy.¹ Only the empty string, "", is falsy.¹
0 (the number) is falsy. "0" is not.
I thought === was for strict equality.
It is. There is no === check in your code. The conditional operator (? :) doesn't do an === check on the condition operand. It does a boolean check, just like if does.
If you used ===, it you'd get false:
var isTrue = value === true ? true : false; // false
Of course, in that case, there's no point to the conditional operator:
var isTrue = value === true; // false
The value I'm receiving will always be a string so I'll check for "0" and "false":
var booleanValue = value && value!=="0" && value!=="false" ? true : false;
It depends on what you want to do and what possible values you might get. For instance, if what you're getting will be a string containing a valid number or a valid boolean (as seems the case from your example there), you could use JSON.parse to parse it to a number or boolean:
var isTrue = !!JSON.parse(str);
(The !! is so that 0 and NaN convert to false and a number that isn't 0 or NaN converts to true.) But again, it depends on what you're receiving, a switch with the values you're expecting may be better, etc.
¹ "falsy" and "truthy":
"falsy" - coerces to false when used as a boolean, such as in a conditional operator as in your question. The falsy values are 0, NaN, null, undefined, "", and of course, false.
"truthy" - coerces to true when used as a boolean. All non-falsy values are truthy, including "0" and "false".
You're inspecting a string containing 0 instead of an actual number 0.
"0" // string
0 // number
A string is considered false if it is equal to '', all other strings are considered true
A number is considered false if it is either 0 or NaN, all other numbers are considered true.
=== indeed means strict equal, meaning a comparison is made on both type and value. So:
true == 1 // true
true === 1 // false
Actually its other way around, for any string, it will return True, for 0 as an integer, it will return False, and for 1 as an integer, it will return True
var value0 = 0;
var value1 = 1;
var str = "23123";
var isTrue0 = value0 ? true : false;
var isTrue1 = value1 ? true : false;
var isTrueStr = str ? true : false;
console.log('0: ' + isTrue0);
console.log('1: ' + isTrue1);
console.log('string: ' + isTrueStr);
isTrue = value - classic error using assignment rather than comparison.

Javascript Optimal way of checking false statement except zero

In javascript we use shortand notation if(input){} to check for empty or null input. We will get false for Null, Undefined, false, 0, NAN, "". My requirements is that I want to get true for any number including zero so I have created a method as follows
function checkFalseExceptZero(value){
if( value !== undefined && value !== null && value !== false && value !== "" && value.length !== 0 ) return true;
else return false;
}
I have added all possible checks in the above method to get the desired result. I am curious if there is any quick, sweet, short or more robust approach to achieve the same?
A simple to understand answer. The three equal signs in JS will not convert type to check if the values equal unlike the two equal signs.
0 == false //true
0 === false //false, because 0 is a number and false is a boolean
Therefore, the answer, if you want to put it inside a function:
JS:
function isNumber(v) {
return typeof v === "number"
}
The function will check the type of the variable. So it is not actually comparing the value to determine the result. The function will only return true if the type of the variable is called number.
Test runs:
isNumber(0) //true
isNumber(false) //false
isNumber("0") //false
isNumber(undefined) //false
In case you want to know, typeof variable will return a string.
My requirements is that I want to get true for any number including
zero so I have created a method as follows
function checkFalseExceptZero(value){
if ( variable.constructor === Array) return !!value.length;
return value === 0 || !!value;
}
This a shorter version of your function. This returns true only when value is 0 or a trully value.
So :
checkFalseExceptZero(null) ==> false;
checkFalseExceptZero(undefined) ==> false;
checkFalseExceptZero(false) ==> false;
checkFalseExceptZero("") ==> false;
checkFalseExceptZero(0) ==> true;
checkFalseExceptZero([]) ==> false;
checkFalseExcpetZero([1]) ==> true;
For any valid number, including 0, JavaScript already exposes the isFinite function. This returns false for all non-numbers, as well as for infinite and NaN
Examples (excerpt from the linked mdn page):
isFinite(Infinity); // false
isFinite(NaN); // false
isFinite(-Infinity); // false
isFinite(0); // true
isFinite(2e64); // true
isFinite("0"); // true, would've been false with the
// more robust Number.isFinite("0")

why in jquery did developers use confusing inverse over straight forward comparisons

function grep( elems, callback, invert ) {
var callbackInverse,
matches = [],
i = 0,
length = elems.length,
callbackExpect = !invert;
// Go through the array, only saving the items
// that pass the validator function
for ( ; i < length; i++ ) {
callbackInverse = !callback( elems[ i ], i );
if ( callbackInverse !== callbackExpect ) {
matches.push( elems[ i ] );
}
}
return matches;
}
wouldn't this be more straight forward
for ( ; i < length; i++ ) {
callbackInverse = callback( elems[ i ], i );
if ( callbackInverse == callbackExpect ) {
matches.push( elems[ i ] );
}
}
I guess it's to make sure both variables are booleans.
For example, imagine callback returns NaN when running
callbackInverse = callback( elems[ i ], i );
That could be problematic, given that
NaN == true; // false
NaN == false; // false
(It happens because the comparisson of a boolean and a number coerced the boolean to a number, instead of coercing the number to boolean)
But negating the values with ! converts them to booleans, avoiding those problems.
Note that callbackExpect is set to !invert:
callbackExpect = !invert;
This forces callbackExpect to be a "boolean" (so exactly true or false).
Then they compare using !== which is not the same as != in that it compares the content of the variable without conversion. In other words, if callbackInverse is not exactly 0 or 1, it returns true.
Note that the inverse of !== is === and not == as in your example. i.e. compare without first converting the parameters.
Update:
As pointed out by Walter Tross in a comment, Boolean is a separate type:
// Booleans
typeof true === 'boolean';
typeof false === 'boolean';
typeof Boolean(true) === 'boolean'; // but never use this form!
Therefore the !invert generates a Boolean and if callbackInverse is not a Boolean, then !== is going to be true. However, like the callbackExpect variable, it is set to !(of something) which means it will always be a Boolean too. So you could use == and != since the ! operator is used to canonicalize the returned values.
Because this way both the invert param and the return value of the callback are cast to boolean by the !, so that they can be safely compared as booleans.
E.g., imagine callback returns undefined. But undefined != false, while you probably want undefined to be treated like false. In fact, casting it to boolean yields false:
!!undefined === false (!! is an easy way of casting to boolean).
Instead of doing the double negation, jQuery does a single one, negating the other side just once, before the loop, so that the comparison becomes:
!undefined === !false (this is a bit like changing the sign of both sides of an equation.)
Quoting the ECMAScript 5.1 standard:
Boolean comparison can be forced by: !a == !b.
The price of doing a single negation instead of a double negation inside the loop is readability (which is always impaired when using "negative logic"), but in a highly optimized library like jQuery this is acceptable.
As to your example, you should rename callbackInverse to something like callbackValue, since it's not inverted (and not cast to boolean) any more. But the problem remains: your code will only work correctly if callback is guaranteed to return booleans.

Why aren't results of logical-not and strict comparison inverses of each other?

Hello fellow JS junkies. Can someone please explain to me the difference between the following ways of evaluating truthiness of variables?
var q1Var1 = "hello",
q1Var2 = 0,
q1Var3 = true,
q1Var4 = "false",
q1Var5 = -1,
q1Var6 = undefined,
q1Var7 = null,
q1Var8;
// What is the difference between this block of code:
console.log( !q1Var1 );
console.log( !q1Var2 );
console.log( !q1Var3 );
console.log( !q1Var4 );
console.log( !q1Var5 );
console.log( !q1Var6 );
console.log( !q1Var7 );
console.log( !q1Var8 );
// and this block?
if( q1Var1 === true ){ console.log( "true" ) } else { console.log( "false" ) };
if( q1Var2 === true ){ console.log( "true" ) } else { console.log( "false" ) };
if( q1Var3 === true ){ console.log( "true" ) } else { console.log( "false" ) };
if( q1Var4 === true ){ console.log( "true" ) } else { console.log( "false" ) };
if( q1Var5 === true ){ console.log( "true" ) } else { console.log( "false" ) };
if( q1Var6 === true ){ console.log( "true" ) } else { console.log( "false" ) };
if( q1Var7 === true ){ console.log( "true" ) } else { console.log( "false" ) };
if( q1Var8 === true ){ console.log( "true" ) } else { console.log( "false" ) };
I was expecting to find that the second block would just be an inverse of the first (in other words, the values would just switch), however, it looks like only the variable set to nonstring "true" actually returns true. Why is this? What is the fundamental difference between the two evaluations:
!q1Var1
vs.
true === q1Var1
This illustrates the notion of "falsy" values in JavaScript. For instance, undefined becomes the same as false in a boolean context (such as an if condition). However, undefined === false is not true. The following are all "falsy" values:
false
undefined
the empty string
the number 0
null
NaN
The === operator means "strictly equal" (see here, for instance); it suppresses automatic type conversions.
Type conversion rules for the == operator (from the second link above) are:
If the two operands are not of the same type, JavaScript converts the operands then applies strict comparison. If either operand is a number or a boolean, the operands are converted to numbers if possible; else if either operand is a string, the other operand is converted to a string if possible. If both operands are objects, then JavaScript compares internal references which are equal when operands refer to the same object in memory.
Strict comparison rules are:
Two strings are strictly equal when they have the same sequence of characters, same length, and same characters in corresponding positions
Two numbers are strictly equal when they are numerically equal (have the same number value). NaN is not equal to anything, including NaN. Positive and negative zeros are equal to one another
Two Boolean operands are strictly equal if both are true or both are false
Two objects are never equal for either strictly or abstract comparisons
An expression comparing Objects is only true if the operands reference the same Object
Null and Undefined Types are == (but not ===)
Note in particular that !var is not the same as var == false (and certainly not the same as var === false if var is not a boolean value to begin with). Non-empty strings are "truthy" (!"..." is always false for any non-empty "..."), but non-empty strings that evaluate to 0 when converted to numbers (like "0") are == false.
When we have 2 different operands of an operation an interpretation (type transformation) of the first value sholuld be made to return the result in the type of the second operand and that is called type cast. In conditional equations the result shoold be boolean type so the result is always casted to boolean, so returning to your question, all this examples are cast of different types to boolean. In javascript casting is made automatically, but in some languages especially when using strict syntax you schould specify the casting by yourself, otherwise your log will be full of errors.
As I understand it, the second set of tests (q1Var1 === true) are looking for absolute equality. It doesn't default to truthiness because it's looking for a perfect match.
Whereas the first set, and I'm a little fuzzy on this bit, I think is testing for an object because the test doesn't have context... at least, I think that's what's happening... o.o
The === operator can be a little confusing and is sometimes overused. When using the === operator, it is important to keep in mind that it compares type and value. Thus, when a statement like this is used:
if( q1Var1 === true )
It requires that q1Var1 be of the same type and value of true. If the situation is setup like this:
q1Var1 = 1;
if (q1Var1 === true) { console.log(true); } else { console.log(false); }//false
Then the console will log false because 1 is not the same type and value as true.
However, using the == operator, the console will log true because 1 is the same value as true.
This can be observed with:
if (1 == true) { console.log(true); } else { console.log(false); }//true
if (1 && true) { console.log(true); } else { console.log(false); }//true
On the other end,
if( !q1Var1 );
tests if q1Var1 is 0. Notably, because false also equates to 0 in value (but still not in type),
if (0 && false) { console.log(true); } else { console.log(false); }//true (same value)
if (0 == false) { console.log(true); } else { console.log(false); }//true (same value)
if (0 === false) { console.log(true); } else { console.log(false); }//false (same value, different type)
this test can be true with numbers as well as the boolean values because there is no test of type.
if (!0) { console.log(true); } else { console.log(false); }//true
if (!false) { console.log(true); } else { console.log(false); }//true

How do I check if a number evaluates to infinity?

I have a series of Javascript calculations that (only under IE) show Infinity depending on user choices.
How does one stop the word Infinity appearing and for example, show 0.0 instead?
if (result == Number.POSITIVE_INFINITY || result == Number.NEGATIVE_INFINITY)
{
// ...
}
You could possibly use the isFinite function instead, depending on how you want to treat NaN. isFinite returns false if your number is POSITIVE_INFINITY, NEGATIVE_INFINITY or NaN.
if (isFinite(result))
{
// ...
}
In ES6, The Number.isFinite() method determines whether the passed value is a finite number.
Number.isFinite(Infinity); // false
Number.isFinite(NaN); // false
Number.isFinite(-Infinity); // false
Number.isFinite(0); // true
Number.isFinite(2e64); // true
A simple n === n+1 or n === n/0 works:
function isInfinite(n) {
return n === n/0;
}
Be aware that the native isFinite() coerces inputs to numbers. isFinite([]) and isFinite(null) are both true for example.
Perform the plain ol’ comparison:
(number === Infinity || number === -Infinity)
or to save several characters:
Math.abs(number) === Infinity
Why to use this
!(Number.isFinite(number)) breaks on NaN inputs.
Number.POSITIVE_INFINITY and Number.NEGATIVE_INFINITY can be redefined; they are configurable.
Infinity and -Infinity are read-only in the strict mode.
It is the shortest solution.
Actually n === n + 1 will work for numbers bigger than 51 bit, e.g.
1e16 + 1 === 1e16; // true
1e16 === Infinity; // false
I like to use Lodash for a variety of defensive coding reasons as well as readability. ES6 Number.isFinite is great and does not have issues with non-numeric values, but if ES6 isn't possible, you already have lodash, or want briefer code: _.isFinite
_.isFinite(Infinity); // false
_.isFinite(NaN); // false
_.isFinite(-Infinity); // false
_.isFinite(null); // false
_.isFinite(3); // true
_.isFinite('3'); // true
I've ran into a scenario that required me to check if the value is of the NaN or Infinity type but pass strings as valid results. Because many text strings will produce false-positive NaN, I've made a simple solution to circumvent that:
const testInput = input => input + "" === "NaN" || input + "" === "Infinity";
The above code converts values to strings and checks whether they are strictly equal to NaN or Infinity (you'll need to add another case for negative infinity).
So:
testInput(1/0); // true
testInput(parseInt("String")); // true
testInput("String"); // false
You can use isFinite in window, isFinite(123):
You can write a function like:
function isInfinite(num) {
return !isFinite(num);
}
And use like:
isInfinite(null); //false
isInfinite(1); //false
isInfinite(0); //false
isInfinite(0.00); //false
isInfinite(NaN); //true
isInfinite(-1.797693134862316E+308); //true
isInfinite(Infinity); //true
isInfinite(-Infinity); //true
isInfinite(+Infinity); //true
isInfinite(undefined); //true
You can also Number.isFinite which also check if the value is Number too and is more accurate for checking undefined and null etc...
Or you can polyfill it like this:
Number.isFinite = Number.isFinite || function(value) {
return typeof value === 'number' && isFinite(value);
}

Categories

Resources