Улучшенная функция isNumeric()?
Во время некоторых проектов мне нужно было проверить некоторые данные и быть как можно более уверенными, что это числовое значение javascript, которое можно использовать в математических операциях.
jQuery и некоторые другие библиотеки javascript уже включают такую функцию, обычно называемую isNumeric. Существует также сообщение о стековерсии, которое широко принимается в качестве ответа, та же самая общая процедура, которую используют вышеупомянутые библиотеки.
function isNumber(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
Будучи моим первым сообщением, я не смог ответить в этой теме. Проблема, которая возникла у меня с принятым постом, заключалась в том, что, как мне кажется, были некоторые угловые случаи, которые повлияли на некоторую работу, которую я выполнял, и поэтому я внес некоторые изменения, чтобы попытаться осветить проблему, которая у меня была.
Во-первых, приведенный выше код вернул бы значение true, если аргумент представлял собой массив длиной 1, и этот единственный элемент имел тип, считающийся числовым по приведенной выше логике. На мой взгляд, если это массив, то он не числовой.
Чтобы облегчить эту проблему, я добавил чек для дисконтирования массивов из логики
function isNumber(n) {
return Object.prototype.toString.call(n) !== '[object Array]' &&!isNaN(parseFloat(n)) && isFinite(n);
}
Конечно, вы также можете использовать Array.isArray
вместо Object.prototype.toString.call(n) !== '[object Array]'
РЕДАКТИРОВАТЬ: я изменил код, чтобы отразить общий тест для массива, или вы можете использовать jquery $.isArray
или прототипы Object.isArray
Вторая проблема заключалась в том, что строки букв с отрицательным шестнадцатеричным целым числом ("-0xA" -> -10) не считались числовыми. Однако положительные шестнадцатеричные целочисленные литеральные строки ("0xA" -> 10) были обработаны как числовые. Мне нужно, чтобы оба были действительными числовыми.
Затем я изменил логику, чтобы принять это во внимание.
function isNumber(n) {
return Object.prototype.toString.call(n) !== '[object Array]' &&!isNaN(parseFloat(n)) && isFinite(n.toString().replace(/^-/, ''));
}
Если вы беспокоитесь о создании регулярного выражения при каждом вызове функции, то вы можете переписать его в закрытии, что-то вроде этого
isNumber = (function () {
var rx = /^-/;
return function (n) {
return Object.prototype.toString.call(n) !== '[object Array]' && !isNaN(parseFloat(n)) && isFinite(n.toString().replace(rx, ''));
};
}());
Затем я взял CMS +30 тестовых случаев и клонировал тестирование на jsfiddle, добавил свои дополнительные тестовые случаи и мое вышеописанное решение.
Кажется, все работает, как ожидалось, и у меня не было никаких проблем. Есть ли какие-то проблемы, кодовые или теоретические, которые вы можете увидеть?
Он не может заменить общепринятый / используемый ответ, но если это то, что вы ожидаете получить в результате выполнения функции isNumeric, то, надеюсь, это поможет вам.
РЕДАКТИРОВАТЬ: Как указал Берги, есть другие возможные объекты, которые можно считать числовыми, и было бы лучше, чтобы белый список, чем черный список. Имея это в виду, я бы добавил к критериям.
Я хочу, чтобы моя функция isNumeric учитывала только числа или строки
Имея это в виду, было бы лучше использовать
function isNumber(n) {
return (Object.prototype.toString.call(n) === '[object Number]' || Object.prototype.toString.call(n) === '[object String]') &&!isNaN(parseFloat(n)) && isFinite(n.toString().replace(/^-/, ''));
}
Это было добавлено в качестве теста 22
7 ответов
На мой взгляд, если это массив, то он не числовой. Чтобы облегчить эту проблему, я добавил чек для дисконтирования массивов из логики
Вы можете иметь эту проблему с любым другим объектом, например, {toString:function(){return "1.2";}}
, Какие объекты вы считаете числовыми? Number
объекты? Никто?
Вместо того, чтобы пытаться занести в черный список некоторые вещи, которые не прошли ваш тест, вы должны явно занести в белый список то, что вы хотите сделать числовым. Что ваша функция должна получить, примитивные строки и числа? Затем протестируйте именно для них:
(typeof n == "string" || typeof n == "number")
Если вы можете использовать регулярные выражения, это может помочь:
function (n)
{
return (Object.prototype.toString.call(n) === '[object Number]' ||
Object.prototype.toString.call(n) === '[object String]') &&
(typeof(n) != 'undefined') && (n!=null) &&
(/^-?\d+((.\d)?\d*(e[-]?\d)?(\d)*)$/.test(n.toString()) ||
/^-?0x[0-9A-F]+$/.test(n.toString()));
}
редактировать: исправлена проблема с шестнадцатеричными числами
Функция isNaN используется для проверки, является ли значение числовым или нет. Если значения являются числовыми, возвращается true, иначе возвращается false.
код:
<script>
function IsNumeric(val) {
if (isNaN(parseFloat(val))) {
return false;
}
return true
}
bool IsNumeric(string);
</script>
Если AMD звучит хорошо для вас, посмотрите на isNumber() mout's.
Как насчет:
function isNumber(value) {
value = Number(value);
return typeof value === 'number' && !isNaN(value) && isFinite(value);
}
function isNumber(value){
return !isNaN(parseFloat(value)) &&
isFinite(value.toString().replace(/^-/, '')) &&
typeof value !== 'object';
}
или же:
function isNumber(value){
return !Array.isArray(value) && !isNaN(parseFloat(value)) &&
isFinite(value.toString().replace(/^-/, '')) &&
Object.prototype.toString.call(value) !== '[object Object]';
}