Этот код в JS дает мне всплывающее окно с надписью "я думаю, что ноль - это число", что меня немного смущает. Что мне не хватает?
if (isNaN(null)) {
alert("null is not a number");
} else {
alert("i think null is a number");
}
Этот код в JS дает мне всплывающее окно с надписью "я думаю, что ноль - это число", что меня немного смущает. Что мне не хватает?
if (isNaN(null)) {
alert("null is not a number");
} else {
alert("i think null is a number");
}
Я считаю, что код пытается спросить: "x
numeric?" с конкретным случаем здесь x = null
. Функция isNaN()
может использоваться для ответа на этот вопрос, но семантически она относится конкретно к значению NaN
. Из Википедии для NaN
:
NaN ( N ot a N umber) - это значение числового типа данных, представляющего undefined или непредставимое значение, особенно в вычислениях с плавающей запятой.
В большинстве случаев мы думаем, что ответ на "нулевой числовой?" не должно быть. Однако isNaN(null) == false
является семантически правильным, потому что null
не NaN
.
Здесь алгоритмическое объяснение:
Функция isNaN(x)
пытается преобразовать переданный параметр в число 1 (эквивалентно Number(x)
), а затем проверяет, имеет ли значение NaN
. Если параметр не может быть преобразован в число, Number(x)
вернет NaN
2. Поэтому, если преобразование параметра x
в число приводит к NaN
, оно возвращает true; в противном случае он возвращает false.
Итак, в конкретном случае x = null
, null
преобразуется в число 0 (попробуйте оценить Number(null)
и увидите, что он возвращает 0), а isNaN(0)
возвращает false. Строка, которая является только цифрами, может быть преобразована в число, а isNaN также возвращает значение false. Строка (например, 'abcd'
), которая не может быть преобразована в число, приведет к тому, что isNaN('abcd')
вернет значение true, особенно потому, что Number('abcd')
возвращает NaN
.
В дополнение к этим очевидным случаям краев являются стандартные числовые причины возврата NaN, как 0/0.
Что касается, казалось бы, непоследовательных тестов для равенства, показанного в вопросе, то поведение NaN
указано таким образом, что любое сравнение x == NaN
является ложным, независимо от другого операнда, включая NaN
себя 1.
Я сам столкнулся с этим вопросом.
Для меня лучший способ использовать isNaN - это так
isNaN(parseInt(myInt))
взяв пример phyzome сверху,
var x = [undefined, NaN, 'blah', 0/0, null, 0, '0', 1, 1/0, -1/0, Number(5)]
x.map( function(n){ return isNaN(parseInt(n))})
[true, true, true, true, true, false, false, false, true, true, false]
(Я выровнял результат в соответствии с вводом, надеюсь, что он упростит чтение.)
Мне кажется лучше.
Это действительно тревожно. Вот массив значений, которые я тестировал:
var x = [undefined, NaN, 'blah', 0/0, null, 0, '0', 1, 1/0, -1/0, Number(5)]
Он оценивает (в консоли Firebug):
,NaN,blah,NaN,,0,0,1,Infinity,-Infinity,5
Когда я вызываю x.map(isNaN)
(для вызова isNaN для каждого значения), я получаю:
true,true,true,true,false,false,false,false,false,false,false
В заключение, isNaN
выглядит довольно бесполезно! ( Изменить: кроме того, что isNaN определен только по номеру, и в этом случае он работает просто отлично - просто с вводящим в заблуждение именем.)
Кстати, вот виды этих значений:
x.map(function(n){return typeof n})
-> undefined,number,string,number,object,number,string,number,number,number,number
(Мой другой комментарий использует практический подход. Здесь теоретическая сторона.)
Я просмотрел стандарт ECMA 262, что и реализует Javascript. Их спецификация isNan:
Применяет ToNumber к его аргументу, затем возвращает true, если результатом является NaN и в противном случае возвращает false.
В разделе 9.3 указано поведение ToNumber
(которое не является вызываемой функцией, а скорее компонентом системы преобразования типов). Чтобы обобщить таблицу, некоторые типы ввода могут создавать NaN. Это тип undefined
, type number
(но только значение NaN
), любой объект, примитивное представление которого NaN
, и любой string
, который не может быть проанализирован. Это оставляет undefined
, NaN
, new Number(NaN)
и большинство строк.
Любой такой ввод, который производит NaN
в качестве выхода при передаче в ToNumber
, будет генерировать a true
при подаче на isNaN
. Поскольку null
может быть успешно преобразовано в число, оно не создает true
.
И вот почему.
Нуль не NaN, а строка не NaN. isNaN() просто проверьте, действительно ли у вас есть объект NaN.
Я не совсем уверен, когда дело доходит до JS, но я видел подобные вещи на других языках, и обычно это происходит потому, что функция проверяет, действительно ли значение null равно NaN (т.е. null === NaN будет false). Другими словами, это не то, что он считает, что нуль на самом деле является числом, но скорее, что null не является NaN. Вероятно, это потому, что оба они представлены по-разному в JS, так что они не будут точно равны, точно так же, как 9! == '9'.
В ES5 он определяется как isNaN (number)
возвращает true, если аргумент принуждает к NaN и в противном случае возвращает false.
И см. Таблица преобразования toNumber абстрактной операции. Таким образом, внутренне js engine оценивает ToNumber(Null)
is +0
, а затем isNaN(null)
есть false
Примечание:
"1" == 1 // true
"1" === 1 // false
Оператор == выполняет преобразование типов, а === - нет.
сайт Дугласа Крокфорда, Yahoo! JavaScript-евангелист, является отличным ресурсом для таких вещей.