Почему isNaN ("") (строка с пробелами) равна false?

В JavaScript почему isNaN(" ") оценивается как false, а isNaN(" x") оценивается как true?

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

Ответ 1

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

Ответ 2

Вы можете найти это удивительное или, может быть, нет, но вот какой-то тестовый код, чтобы показать вам неловкость движка 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

но

"" != " "

Удачи:)

Ответ 3

Чтобы понять это лучше, откройте Ecma- Script spec pdf на стр. 43 "ToNumber Applied to String Type"

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

isNaN('Infinity'); // false

Ответ 4

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

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

или

alert(isNaN(parseFloat("    ")));

Ответ 5

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

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

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

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

Ответ 6

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

alert(' ' * 1); // 0
alert('x' * 1); // NaN

Ответ 7

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

var isNumber = function isNumber(value) {
   return typeof value === 'number' && 
   isFinite(value);
}

Ответ 8

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

Антонио Хейли высокоподдерживаемый и принятый ответ здесь делает неправильное предположение, что этот процесс проходит через функцию JavaScript parseInt:

Вы можете использовать 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 вызывается с одним номером аргумента, выполняются следующие шаги:

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

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

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

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

Строка примера " " поэтому преобразуется в +0, что является числом.

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

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

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

Ответ 9

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

Ответ 10

Функция isNaN("") выполняет принуждение типа String to Number

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

  • undefined
  • объект (нуль, объекты, массивы)
  • булева
  • номер
  • строка
  • Функция

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

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

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

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

if (!isNaN(s) && s.toString().trim()!='') // 's' can be boolean, number or string
    alert("s is a number")

Ответ 11

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

function isInteger(s)
{
   return Math.ceil(s) == Math.floor(s);
}

Ответ 12

То, что isNaN(" ") является ложным, является частью запутанного поведения глобальной функции isNaN из-за его принуждения не чисел к числовому типу.

Из MDN:

Поскольку самые ранние версии спецификации функции isNaN, ее поведение для нечисловых аргументов сбивает с толку. Когда аргумент функции isNaN не относится к типу Number, значение сначала принудительно вводится в число. Полученное значение затем проверяется, чтобы определить, является ли оно NaN. Таким образом, для не-чисел, которые при принуждении к числовому типу приводят к действительному числовому значению, отличному от NaN (в частности, к пустым строкам и булевым примитивам, которые при принуждении дают числовые значения ноль или один), возвращаемое значение "false" может быть неожиданным; пустая строка, например, "не является числом".

Обратите также внимание, что в ECMAScript 6 также существует метод Number.isNaN, который согласно MDN:

По сравнению с глобальной функцией isNaN(), Number.isNaN() не сталкивается с проблемой принудительного преобразования параметра в число. Это означает, что теперь безопасно передавать значения, которые обычно конвертируются в NaN, но на самом деле не имеют значения NaN. Это также означает, что только значения номера типа, которые также являются NaN, возвращают true.

К сожалению,

Даже метод ECMAScript 6 Number.isNaN имеет свои проблемы, как указано в сообщении в блоге - Устранение уродливой проблемы JavaScript и ES6 NaN.

Ответ 13

Функция isNaN ожидает в качестве аргумента Number, поэтому аргументы любого другого типа (в вашем случае строки) будут преобразованы в число до того, как будет выполнена фактическая логика функции. (Имейте в виду, что NaN также является значением типа Number!)

Btw. это является общим для всех встроенных функций - если они ожидают аргумент определенного типа, фактический аргумент будет преобразован с использованием стандартных функций преобразования. Существуют стандартные преобразования между всеми базовыми типами (bool, string, number, object, date, null, undefined.)

Стандартное преобразование для String в Number может быть вызвано явным с помощью Number(). Таким образом, мы можем видеть, что:

  • Number(" ") оценивается как 0
  • Number(" x") имеет значение NaN

Учитывая это, результат функции isNaN полностью логичен!

Реальный вопрос заключается в том, почему стандартное преобразование String-to-Number работает так же, как и оно. Преобразование строк в число действительно предназначено для преобразования числовых строк типа "123" или "17.5e4" в эквивалентные числа. Сначала конверсия пропускает начальные пробелы (так что "123" действительно), а затем пытается разобрать остатки в виде числа. Если он не обрабатывается как число ( "x" - нет), то результатом является NaN. Но существует явное специальное правило, что строка, которая пуста или только пробел, преобразуется в 0. Таким образом, это объясняет преобразование.

Ссылка: http://www.ecma-international.org/ecma-262/5.1/#sec-9.3.1

Ответ 14

Как и объяснялось, функция isNaN будет принуждать пустую строку к числу перед ее проверкой, тем самым изменяя пустую строку на 0 (это допустимое число). Однако я обнаружил, что функция parseInt вернет NaN при попытке разобрать пустую строку или строку только с пробелами. Таким образом, следующая комбинация, кажется, работает хорошо:

if ( isNaN(string) || isNaN(parseInt(string)) ) console.log('Not a number!');

Эта проверка будет работать для положительных чисел, отрицательных чисел и чисел с десятичной точкой, поэтому я считаю, что она охватывает все распространенные числовые случаи.

Ответ 15

isNaN всегда возвращает false для строки ничего, кроме пробелов. Я бы предложил сделать обрезку строк перед оценкой.

Ответ 16

Эта функция, казалось, работала в моих тестах

function isNumber(s) {
    if (s === "" || s === null) {
        return false;
    } else {
        var number = parseInt(s);
        if (number == 'NaN') {
            return false;
        } else {
            return true;
        }
    }
}

Ответ 17

Что насчет

function isNumberRegex(value) {        
    var pattern = /^[-+]?\d*\.?\d*$/i;
    var match = value.match(pattern);
    return value.length > 0 && match != null;
}

Ответ 18

Я написал эту небольшую функцию, чтобы помочь решить эту проблему.

function isNumber(val) {
     return (val != undefined && val != null && val.toString().length > 0 && val.toString().match(/[^0-9\.\-]/g) == null);
};

Он просто проверяет любые символы, которые не являются числовыми (0-9), которые не являются "-" или ".", и которые не являются undefined, пустыми или пустыми и возвращают true, если нет Матчи.:)

Ответ 19

Функция JavaScript встроенная isNaN, как и следовало ожидать по умолчанию, - "Оператор динамического типа". Поэтому все значения, которые (во время процесса DTC) могут привести к простому истинному | false, например "", " ", " 000", не может быть NaN.

Значение, которое предоставленный аргумент будет сначала преобразован, как в:

function isNaNDemo(arg){
   var x = new Number(arg).valueOf();
   return x != x;
}

Объяснение:

В верхней строке тела функции мы (сначала) пытаемся успешно преобразовать аргумент в числовой объект. И (второй), используя точечный оператор, мы - для нашего удобства - сразу же отбрасываем значение примитивного созданного объекта.

Во второй строке мы берем значение, полученное на предыдущем шаге, и преимущество того, что NaN не равно никому во вселенной, даже самому себе, например: NaN == NaN >> false, чтобы окончательно сравнить его (для неравенства) с самим собой.

Таким образом, возврат функции приведет к true только тогда и только тогда, когда поставляемый аргумент-возврат является неудачной попыткой преобразования в числовой объект, т.е. не-число номер; например NaN.


isNaNstatic()

Однако для оператора статического типа - при необходимости и при необходимости - мы можем написать гораздо более простую функцию, такую ​​как:

function isNaNstatic(x){   
   return x != x;
}

И вообще избегайте кода DTC, так что если аргумент явно не является номером NaN, он вернет false. Поэтому тестирование на следующее:

isNaNStatic(" x"); // will return false, потому что это еще строка.

Тем не менее: isNaNStatic(1/"x"); // will of course return true., как это будет, например, isNaNStatic(NaN); >> true.

Но вопреки isNaN, isNaNStatic("NaN"); >> false, потому что он (аргумент) является обычной строкой.

p.s.: Статическая версия isNaN может быть очень полезна в современных сценариях кодирования. И это вполне может быть одной из главных причин, по которым я потратил свое время для публикации этого.

С уважением.

Ответ 20

isNAN(<argument>) - это функция, указывающая, является ли данный аргумент незаконным числом. isNaN выводит аргументы в тип Number. Если вы хотите проверить, является ли аргумент числовым или нет? Используйте функцию $.isNumeric() в jQuery.

То есть isNaN (foo) эквивалентно isNaN (Number (foo)) Он принимает любые строки со всеми числами как цифры по понятным причинам. Например,

isNaN(123) //false
isNaN(-1.23) //false
isNaN(5-2) //false
isNaN(0) //false
isNaN('123') //false
isNaN('Hello') //true
isNaN('2005/12/12') //true
isNaN('') //false
isNaN(true) //false
isNaN(undefined) //true
isNaN('NaN') //true
isNaN(NaN) //true
isNaN(0 / 0) //true

Ответ 21

Я использую этот

    function isNotANumeric(val) {
    	if(val.trim && val.trim() == "") {
         return true;
      } else {
      	 return isNaN(parseFloat(val * 1));
      }
    }
    
    alert(isNotANumeric("100"));  // false
    alert(isNotANumeric("1a"));   // true
    alert(isNotANumeric(""));     // true
    alert(isNotANumeric("   "));  // true

Ответ 22

NaN ! == "не число"

NaN - значение типа номера

это определение isNaN() в ECMAScript

1. Let num be ToNumber(number).
2. ReturnIfAbrupt(num).
3. If num is NaN, return true.
4. Otherwise, return false.

Попробуйте преобразовать любое значение в Number.

Number(" ") // 0
Number("x") // NaN
Number(null) // 0

Если вы хотите определить, является ли значение NaN, сначала попробуйте преобразовать его в значение "Число".

Ответ 23

При проверке, может ли определенное строковое значение с пробелом или " " is isNaN возможно, попытаться выполнить проверку строки, например:

//value = "123 " if (value.match(/\s/) || isNaN(value)) {//do something }