Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does `isFinite(null) === true`?

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