Can I write a isNan() function with JavaScript? Can JavaScript check for sure that a variable is NaN without native isNaN function?
This is a interview question.
If it is a number, and is not equal to itself, it is NaN.
Note: As #pst has pointed out, the number constraint is unnecessary. NaN appears to be the only value in JS != itself.
Complete solution for this question:
var is_NaN = function(n) {
return (n !== n);
}
is_NaN(1/'a'); // true
isNaN(1/'a'); // true
Because in JavaScript NaN isn't equal to itself. An expression NaN === NaN always returns false
The second solution:
You can use built-in isFinite function. isFinite checks whether the input is a number that is neither Infinity nor NaN.
isFinite(NaN) // false
isFinite(Infinity) // false
isFinite(1) // true
isFinite(true) // true, because argument true is equal to 1
isFinite('a') // false
isFinite(1/'a') // false
ECMA 6
Number.isNaN(42) === false
Number.isNaN(NaN) === true
http://es6-features.org/#NumberTypeChecking
Related
let x;
console.log("shubham" == true ); // gives false
"shubham" ? x=2 : x=3;
console.log(x); // gives 2, so "shubham" must be true?
//I am hoping to get value 3
when you use this:
"shubham" == true
before comparing, true turned to 1,so the actually comparsion is
"shubham" == 1
so ,it gives false;
the book:
When performing conversions, the equal and not-equal operators follow
these basic rules:
If an operand is a Boolean value, convert it into a
numeric value before checking for equality. A value of false converts
to 0, whereas a value of true converts to 1.
If one operand is a string and the other is a number, attempt to convert the string into a number before checking for equality.
when you use this:
"shubham" ? x=2 : x=3;
works like:
Boolean("shubham")?x=2:x=3
so,it gives you x=2;
the book:
variable = boolean_expression ? true_value : false_value;
This basically allows a conditional assignment to a variable depending
on the evaluation of the boolean_expression. If it’s true, then
true_value is assigned to the variable; if it’s false, then
false_value is assigned to the variable.
the book:
Professional JavaScript for Web Developers.3rd.Edition.Jan.2012
Yes, this is due to the underlying code behind the 'if' statement in Javascript. It relies on a method 'ToBoolean' which converts the condition of the if statement to a boolean value. Any string that is not empty, is converted to true. Thus, why you get the above logic.
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.
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.
Try it: In Node.js, or Firefox, open a REPL, and type:
Number.isNaN('asdf');
How can this not be NaN? What is NaN if not this?
You have a misconception here. The fact that NaN means Not a Number does not mean that anything that is not a number is a NaN.
NaN is a special value on floating point arithmethic that represents an undefined result of an operation. For example, 0 / 0 generally yields NaN as a result.
More information here and here.
There is no notion of Number.isNaN() in the language specification. The only specified function is the global isNaN (15.1.2.4), which will correctly return true on anything that isn't a number or cannot get correctly transformed into a number.
Number.isNaN (which returns true on NaN) is probably an implementation detail part of the next standard draft (see remyabel' answer) which could be used internally by isNaN.
Just a note, it seems that Number.IsNaN has limited support.
This output:
console.log(Number.isNaN("blabla"));
Gives false, and false !== NaN:
console.log(false !== NaN)
console.log(false !== Number.NaN);
Here's a reference:
When the Number.isNaN is called with one argument number, the
following steps are taken:
If Type(number) is not Number, return false.
If number is NaN, return true.
Otherwise, return false.
This function differs from the global isNaN function (18.2.3) is that
it does not convert its argument to a Number before determining
whether it is NaN.
I am l33t for I have 1337 reputation.
Try this:
function checkNaN(value)
{
return value !== value;
}
It works because (I believe) NaN is the only thing in JS that does not strictly equal itself.
This is part of the EcmaScript 6 Standard.
Number.isNaN returns whether a value is NaN without coercing the parameter.
Number.isNaN("xmfds"); // false
Number.isNaN("ose"); // false
isNaN returns whether the value is NaN after coercing the parameter to Number type.
isNaN("ose") -> isNaN( Number("ose") ) -> isNaN(NaN); // true