Вопрос

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

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

Спасибо!

Это было полезно?

Решение

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

Другие советы

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

но

"" != " "

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

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

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

isNaN('Infinity'); // false

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

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

Или

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

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

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

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

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

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

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

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

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

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

Антонио Хейли ответ, получивший большое количество голосов и принятый здесь делается неверное предположение, что этот процесс проходит через 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 функция вызывается с одним номером аргумента, выполняются следующие шаги:

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

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

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

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

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

В том же разделе также указано:

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

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

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

Функция 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)
}

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

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

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

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

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

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

От МДН:

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

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

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

К сожалению:

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

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

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

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

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

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

Как насчет

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

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

Кстати.это обычное дело для все встроенные функции — если они ожидают аргумент определенного типа, фактический аргумент будет преобразован с использованием стандартных функций преобразования.Существуют стандартные преобразования между всеми базовыми типами (bool, строка, число, объект, дата, ноль, неопределенное).

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

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

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

Реальный вопрос заключается в том, почему стандартное преобразование строки в число работает именно так.Преобразование строки в число на самом деле предназначено для преобразования числовых строк, таких как «123» или «17.5e4», в эквивалентные числа.Преобразование сначала пропускает начальные пробелы (так что «123» является допустимым), а затем пытается проанализировать остатки как число.Если оно не поддается синтаксическому анализу как число («x» не является), то результатом будет NaN.Но существует специальное правило, согласно которому пустая строка или строка, состоящая только из пробелов, преобразуется в 0.Это объясняет преобразование.

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

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

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

Он просто проверяет наличие любых символов, которые не являются цифрами (0–9), которые не являются «-» или «.», а также не являются неопределенными, нулевыми или пустыми, и возвращает true, если совпадений нет.:)

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

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

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

Объяснение:

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

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

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


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 потому что это (аргумент) — обычная строка.

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

С уважением.

isNAN(<argument>) — это функция, позволяющая определить, является ли данный аргумент недопустимым числом.isNaN преобразует аргументы в числовой тип.Если вы хотите проверить, является ли аргумент числовым или нет?Пожалуйста, используйте $.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

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

    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

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(" ") // 0
Number("x") // NaN
Number(null) // 0

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top