Почему isNaN ("") равно ложному - PullRequest
148 голосов
/ 05 мая 2009

У меня быстрый вопрос (надеюсь!). В JS почему isNaN(" ") оценивается как ложное, а isNaN(" x") оценивается как истинное?

Я выполняю числовые операции над полем ввода текста и проверяю, является ли поле пустым, "" или NaN. Когда кто-то вводит в поле несколько пробелов, моя проверка завершается неудачно на всех трех, и я не понимаю, почему он проходит проверку isNAN.

Спасибо!

Ответы [ 22 ]

145 голосов
/ 05 мая 2009

JavaScript интерпретирует пустую строку как 0, что затем не проходит тест isNAN. Сначала вы можете использовать parseInt для строки, которая не преобразует пустую строку в 0. Затем результат должен завершиться ошибкой isNAN.

76 голосов
/ 05 мая 2009

Вы можете найти это удивительным, а может и нет, но вот тестовый код, который покажет вам причуду движка JavaScript.

document.write(isNaN("")) // false
document.write(isNaN(" "))  // false
document.write(isNaN(0))  // false
document.write(isNaN(null)) // false
document.write(isNaN(false))  // false
document.write("" == false)  // true
document.write("" == 0)  // true
document.write(" " == 0)  // true
document.write(" " == false)  // true
document.write(0 == false) // true
document.write(" " == "") // false

, значит,

" " == 0 == false

и

"" == 0 == false

но

"" != " "

Веселитесь:)

16 голосов
/ 05 мая 2009

Чтобы лучше это понять, откройте Спецификация Ecma-Script pdf на стр. 43 "ToNumber, примененный к типу строки"

если строка имеет числовой синтаксис, который может содержать любое количество символов пробела, она может быть преобразована в тип Number. Пустая строка оценивается как 0. Также строка 'Infinity' должна дать

isNaN('Infinity'); // false
15 голосов
/ 05 мая 2009

Попробуйте использовать:

alert(isNaN(parseInt("   ")));

Или

alert(isNaN(parseFloat("    ")));
6 голосов
/ 03 мая 2015

С MDN причина проблемы, с которой вы столкнулись

Когда аргумент функции isNaN не имеет типа Number, значение сначала приводится к Number. Полученное значение затем проверяется, чтобы определить, является ли оно NaN.

Вы можете проверить следующий исчерпывающий ответ, который также охватывает сравнение NaN на равенство.

Как проверить, является ли переменная JavaScript NaN

5 голосов
/ 05 мая 2009

Я думаю, это из-за набора текста в Javascript: ' ' конвертируется в ноль, тогда как 'x' не:

alert(' ' * 1); // 0
alert('x' * 1); // NaN
4 голосов
/ 10 марта 2016

Не совсем правильный ответ

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1006

Вы можете использовать parseInt для строки ... Результат должен завершиться ошибкой isNAN.

Мы можем легко опровергнуть это утверждение строкой "123abc":

parseInt("123abc")    // 123     (a number...
isNaN("123abc")       // true     ...which is not a number)

Таким образом, мы можем видеть, что функция JavaScript parseInt возвращает "123abc" как число 123, но ее функция isNaN сообщает нам, что "123abc" не число.

Правильный ответ

ECMAScript-262 определяет, как работает проверка isNaN в

разделе 18.2.3 .

18.2.3 isNaN (число)

Функция isNaN является внутренним объектом %isNaN%. Когда функция isNaN вызывается с одним номером аргумента, предпринимаются следующие шаги:

  1. Пусть num будет? ToNumber(number).
  2. Если num равно NaN, вернуть true.
  3. В противном случае вернуть false.

Функция ToNumber, на которую она ссылается, также определена в разделе ECMAScript-262 7.1.3 . Здесь нам рассказывают, как JavaScript обрабатывает строки, которые передаются этой функции.

Первый пример, приведенный в вопросе, представляет собой строку, содержащую только пробельные символы. В этом разделе говорится, что:

A StringNumericLiteral, который пуст или содержит только пробел, преобразуется в +0.

Пример строки " ", следовательно, преобразуется в +0, что является числом.

В том же разделе также говорится:

Если грамматика не может интерпретировать String как расширение StringNumericLiteral, то результатом ToNumber будет NaN.

Без цитирования всех проверок, содержащихся в этом разделе, приведенный в вопросе пример " x" попадает в указанное выше условие, поскольку его нельзя интерпретировать как StringNumericLiteral. Поэтому " x" преобразуется в NaN.

4 голосов
/ 05 мая 2009

Если вы хотите реализовать точную функцию isNumber, вот один из способов сделать это из Javascript: The Good Parts Дугласа Крокфорда [страница 105]

var isNumber = function isNumber(value) {
   return typeof value === 'number' && 
   isFinite(value);
}
2 голосов
/ 14 сентября 2013

Функция isNaN("") выполняет приведение типа Строка к номеру

ECMAScript 3-5 определяет следующие возвращаемые значения для оператора typeof:

  • неопределенный
  • объект (ноль, объекты, массивы)
  • логическое
  • номер
  • строка
  • функция

Лучше обернуть наш тест в функциональное тело:

function isNumber (s) {
    return typeof s == 'number'? true
           : typeof s == 'string'? (s.trim() === ''? false : !isNaN(s))
           : (typeof s).match(/object|function/)? false
           : !isNaN(s)
}

Эта функция не предназначена для проверки переменной type , вместо этого она проверяет принудительное значение . Например, логические значения и строки приводятся к числам, поэтому, возможно, вы захотите вызвать эту функцию как isNumberCoerced()

если нет необходимости проверять типы , отличные от string и number , то следующий фрагмент может использоваться как часть некоторого условия:

if (!isNaN(s) && s.toString().trim()!='') // 's' can be boolean, number or string
    alert("s is a number")
2 голосов
/ 05 мая 2009

Я не уверен, почему , но чтобы обойти проблему, вы всегда можете обрезать пробелы перед проверкой. Вы, вероятно, все равно хотите это сделать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...