Почему `isFinite (null) === true`?
Ниже приводятся примеры, которые имеют смысл для меня.
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 not even a number
typeof document // "object"
Ниже я смущаюсь.
isFinite(null) // true - Wait what? Other non-number objects returned false. I see no reason?
typeof null // "object"
Я просто не вижу причин для этого.
То, что я хотел бы, это самый низкий уровень ответа.
Я думаю, что null
преобразуется в 0, почему? Какие еще воздействия это имеет?
Ответы
Ответ 1
Спецификация ECMAScript (5.1) определяет isFinite
как таковой:
isFinite (число)
Возвращает false, если аргумент принуждает к NaN, + ∞ или -∞ и в противном случае возвращает true.
Если ToNumber (число) - NaN, + ∞ или -∞, верните false.
В противном случае верните true.
Другими словами, isFinite
вызывает ToNumber о том, что передавалось, а затем сравнивая его с любой константой pos/neg или NaN.
В JavaScript (обратите внимание на использование !=
вместо более общего !==
, вызывающего тип cast):
function isFinite(someInput) {
return !isNaN(someInput) &&
someInput != Number.POSITIVE_INFINITY &&
someInput != Number.NEGATIVE_INFINITY;
}
(Как отмечено в ниже комментарии, someInput != NaN
не требуется, поскольку NaN
определяется как не эквивалентный всем, включая сам.)
Теперь, почему null
преобразован в ноль (в отличие от undefined
)? Как TylerH говорит в комментариях, null
означает, что значение существует, но пусто. Математическое представление этого значения равно 0. undefined
означает, что там нет значения, поэтому мы получаем NaN
при попытке называть ToNumber
на нем.
http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.2.5
Тем не менее, ECMAScript 6 несет неконвертирующее isFinite
как свойство Number
. Дуглас Крокфорд предложил это здесь: http://wiki.ecmascript.org/doku.php?id=harmony:number.isfinite
Ответ 2
Из MDN:
Глобальная функция isFinite() определяет, является ли переданное значение конечное число. При необходимости параметр сначала преобразуется в число.
Итак, он преобразуется в число...
isFinite(null)
isFinite(+null) //convert to a number
isFinite(0) // true because +null or Number(null) = 0
Спектр говорит, что глобальный метод isFinite()
будет принудительно преобразовывать параметр в число.
Однако вы могли использовать (на свой страх и риск) спецификацию EcmaScript 6 Number.isFinite()
, которая не выполняет это преобразование.
Number.isFinite(null) // false
Или, как lodash и подчеркивание, сделайте это...
var _.isFinite = function(obj) {
return isFinite(obj) && !isNaN(parseFloat(obj));
};
Ответ 3
isFinite
вызывает ToNumber
свой аргумент. Так
> Number(null)
0
> Number(document)
NaN
> isFinite(0)
true
> isFinite(NaN)
false
> isFinite(null)
true
> isFinite(document)
false
Ответ 4
Потому что, если вы скажете
Number(null) === 0
, который конечен
См. Конверсии чисел
Что говорит, что для типа аргумента null
результат +0
Ответ 5
isFinite
выводит аргумент в число, если оно уже не является числом. По существу у вас есть isFinite(Number(null))
и Number(null) === 0
. Которое конечно.
Ответ 6
Помимо null
, вы также найдете эти примеры:
alert(isFinite(' ')); //true
alert(isFinite('')); //true
alert(isFinite(null)); //true
alert(isFinite(!undefined)); //true
В явном преобразовании JavaScript происходит. Это преобразование пытается преобразовать bool в integer при сравнении чисел с логическим значением или числом в строку при сравнении строки с числами. Если вы обрабатываете любой тип данных как число, он неявно преобразуется в число, поэтому все вышеприведенные случаи возвращают нулевой конечный результат. См. здесь
Если вы попробуете Number(undefined)
, он даст вам NaN
при отрицании, это приведет к 1 конечному.