Ответ 1
JavaScript интерпретирует пустую строку как 0, которая затем терпит неудачу в тесте isNAN. Вы можете использовать parseInt в первой строке, которая не преобразует пустую строку в 0. Результат должен быть неудачным isNAN.
В JavaScript почему isNaN(" ")
оценивается как false
, а isNaN(" x")
оценивается как true
?
Я выполняю числовые операции над полем ввода текста, и я проверяю, является ли поле 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 spec pdf на стр. 43 "ToNumber Applied to String Type"
если строка имеет численный синтаксис, который может содержать любое количество символов пробела, его можно преобразовать в тип номера. Пустая строка оценивается как 0. Также строка 'Infinity' должна давать
isNaN('Infinity'); // false
Попробуйте использовать:
alert(isNaN(parseInt(" ")));
или
alert(isNaN(parseFloat(" ")));
От MDN
причина проблемы, с которой вы сталкиваетесь
Когда аргумент функции isNaN не имеет тип Number, значение сначала принудительно вводится в число. Полученное значение затем проверяется, чтобы определить, является ли это NaN.
Вы можете проверить следующий всеобъемлющий ответ, который также охватывает сравнение NaN для равенства.
Я думаю, это из-за ввода Javascript: ' '
преобразуется в ноль, тогда как 'x'
не является:
alert(' ' * 1); // 0
alert('x' * 1); // NaN
Если вы хотите реализовать точную функцию isNumber, вот один из способов сделать это из Javascript: The Good Parts by Douglas Crockford [стр. 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
вызывается с одним номером аргумента, выполняются следующие шаги:
- Пусть
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
.
Я не уверен, почему, но чтобы обойти эту проблему, вы всегда можете обрезать пробелы перед проверкой. Вероятно, вы все равно захотите сделать это.
Функция isNaN("")
выполняет принуждение типа String to Number
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
из-за его принуждения не чисел к числовому типу.
Из 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.
Функция 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
Как и объяснялось, функция isNaN
будет принуждать пустую строку к числу перед ее проверкой, тем самым изменяя пустую строку на 0 (это допустимое число).
Однако я обнаружил, что функция parseInt
вернет NaN
при попытке разобрать пустую строку или строку только с пробелами. Таким образом, следующая комбинация, кажется, работает хорошо:
if ( isNaN(string) || isNaN(parseInt(string)) ) console.log('Not a number!');
Эта проверка будет работать для положительных чисел, отрицательных чисел и чисел с десятичной точкой, поэтому я считаю, что она охватывает все распространенные числовые случаи.
isNaN всегда возвращает false для строки ничего, кроме пробелов. Я бы предложил сделать обрезку строк перед оценкой.
Эта функция, казалось, работала в моих тестах
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;
}
Я написал эту небольшую функцию, чтобы помочь решить эту проблему.
function isNumber(val) {
return (val != undefined && val != null && val.toString().length > 0 && val.toString().match(/[^0-9\.\-]/g) == null);
};
Он просто проверяет любые символы, которые не являются числовыми (0-9), которые не являются "-" или ".", и которые не являются undefined, пустыми или пустыми и возвращают true, если нет Матчи.:)
Функция 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 может быть очень полезна в современных сценариях кодирования. И это вполне может быть одной из главных причин, по которым я потратил свое время для публикации этого.
С уважением.
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
Я использую этот
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.
Number(" ") // 0
Number("x") // NaN
Number(null) // 0
Если вы хотите определить, является ли значение NaN
, сначала попробуйте преобразовать его в значение "Число".
При проверке, может ли определенное строковое значение с пробелом или " "
is isNaN
возможно, попытаться выполнить проверку строки, например:
//value = "123 " if (value.match(/\s/) || isNaN(value)) {//do something }