I'm learning some JavaScript and ran into a quirk and was wondering if anyone knew a way to override this behavior. I'd like to be able to test if a value passed to a function is a real number, and I thought using ===
for the isNaN()
check would take care of that, but it doesn't.
Example function:
var foodDemand = function(food) {
if (isNaN(food) === false) {
console.log("I can't eat " + food + " because it's a number");
} else {
console.log("I want to eat " + food);
}
};
And I test with this:
// behaves as expected
foodDemand("steak");
foodDemand(999999999);
foodDemand(0.0000001337);
foodDemand([1]);
foodDemand(undefined);
foodDemand(NaN);
foodDemand({});
// converts non-number to a number
foodDemand("42");
foodDemand("");
foodDemand(null);
foodDemand([]);
foodDemand("\n");
Output (italics represent unexpected results):
I want to eat steak I can't eat 999999999 because it's a number I can't eat 1.337e-7 because it's a number I can't eat 1 because it's a number I want to eat undefined I want to eat NaN I want to eat [object Object] I can't eat 42 because it's a number I can't eat because it's a number I can't eat null because it's a number I can't eat because it's a number I can't eat because it's a number
Is there any way to make isNaN()
more strict?
I'm learning some JavaScript and ran into a quirk and was wondering if anyone knew a way to override this behavior. I'd like to be able to test if a value passed to a function is a real number, and I thought using ===
for the isNaN()
check would take care of that, but it doesn't.
Example function:
var foodDemand = function(food) {
if (isNaN(food) === false) {
console.log("I can't eat " + food + " because it's a number");
} else {
console.log("I want to eat " + food);
}
};
And I test with this:
// behaves as expected
foodDemand("steak");
foodDemand(999999999);
foodDemand(0.0000001337);
foodDemand([1]);
foodDemand(undefined);
foodDemand(NaN);
foodDemand({});
// converts non-number to a number
foodDemand("42");
foodDemand("");
foodDemand(null);
foodDemand([]);
foodDemand("\n");
Output (italics represent unexpected results):
I want to eat steak I can't eat 999999999 because it's a number I can't eat 1.337e-7 because it's a number I can't eat 1 because it's a number I want to eat undefined I want to eat NaN I want to eat [object Object] I can't eat 42 because it's a number I can't eat because it's a number I can't eat null because it's a number I can't eat because it's a number I can't eat because it's a number
Is there any way to make isNaN()
more strict?
Number.isNaN()
, which does not perform the type conversion.
– Pointy
Commented
Apr 15, 2015 at 19:25
isNaN
's purpose is not really to test if something is litterally not a number, but to test if something is the number NaN (since NaN===NaN
returns false in JavaScript you can't use equality).
You should use typeof
instead, and then isNaN:
if((typeof food)==="number" && !isNaN(food))
Why, you may ask, is NaN
not equal to NaN
?? Is that one more of JavaScript's infamous quirks?
Turns out there is a good reason for this behavior. Mathematical operations that can't return a real result, not even Infinity, will not plain and throw an error. They just return NaN. For example, 0/0, sqrt(-1), acos(2). Wouldn't it be weird to have Math.sqrt(-1) === 0/0
? So NaN is not equal to even itself. And therefore, a primitive like isNaN
is needed in case you actually want to check if a value is NaN.
isNaN() is not checking if something is not a number type, its literally checking if something is the value "NaN", as you've found. typeof
is your friend here.
((typeof foo) === 'number') && !isNaN(foo)
should work for what you want.
The purpose of the isNaN
function is to check if a value is exactly equal to the built-in NaN
constant value. It shouldn't be used to check if something is a number or not, even if that might seem counter-intuitive. It only exists because NaN === NaN
returns false, so it's the only way to check if a function involving numbers failed.
Try this:
if (typeof food == "number") {
console.log("I can't eat " + food + " because it's a number");
} else {
console.log("I want to eat " + food);
}