javascript - number - ¿Una función isNumeric() mejorada?
validate decimal javascript (7)
Durante algunos proyectos, he necesitado validar algunos datos y estar tan seguro como sea posible de que es un valor numérico de JavaScript que se puede usar en operaciones matemáticas.
jQuery, y algunas otras bibliotecas de JavaScript ya incluyen dicha función, generalmente llamada isNumeric. También hay una publicación en stackoverflow que ha sido ampliamente aceptada como la respuesta, la misma rutina general que utilizan las bibliotecas mencionadas anteriormente.
function isNumber(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
Al ser mi primera publicación, no pude responder en ese hilo. El problema que tuve con la publicación aceptada fue que parece haber algunos casos de esquina que afectaron el trabajo que estaba haciendo, así que hice algunos cambios para tratar de cubrir el problema que estaba teniendo.
Primero, el código anterior devolvería verdadero si el argumento era una matriz de longitud 1, y ese único elemento era de un tipo considerado como numérico por la lógica anterior. En mi opinión, si se trata de una matriz, entonces no es numérica.
Para aliviar este problema, agregué un cheque para descontar matrices de la lógica
function isNumber(n) {
return Object.prototype.toString.call(n) !== ''[object Array]'' &&!isNaN(parseFloat(n)) && isFinite(n);
}
Por supuesto, también puede usar Array.isArray
lugar de Object.prototype.toString.call(n) !== ''[object Array]''
EDITAR: He cambiado el código para que refleje una prueba genérica para array, o podría usar jquery $.isArray
o prototipos Object.isArray
Mi segundo problema fue que las cadenas literales de entero hexadecimal negativo ("-0xA" -> -10) no se contaban como numéricas. Sin embargo, las cadenas literales de entero hexadecimal positivo ("0xA" -> 10) se trataron como numéricas. Necesitaba que ambos fueran numéricos válidos.
Luego modifiqué la lógica para tener esto en cuenta.
function isNumber(n) {
return Object.prototype.toString.call(n) !== ''[object Array]'' &&!isNaN(parseFloat(n)) && isFinite(n.toString().replace(/^-/, ''''));
}
Si le preocupa la creación de la expresión regular cada vez que se llama a la función, entonces puede volver a escribirla dentro de un cierre, algo como esto
isNumber = (function () {
var rx = /^-/;
return function (n) {
return Object.prototype.toString.call(n) !== ''[object Array]'' && !isNaN(parseFloat(n)) && isFinite(n.toString().replace(rx, ''''));
};
}());
Luego tomé CMSs +30 casos de prueba y cloné las pruebas en jsfiddle agregué mis casos de prueba adicionales y mi solución descrita anteriormente.
Todo parece estar funcionando como se esperaba y no he tenido ningún problema. ¿Hay algún problema, código o teoría, que pueda ver?
Es posible que no reemplace la respuesta ampliamente aceptada / utilizada, pero si esto es lo que está esperando como resultado de su función isNumeric, con suerte, esto será de alguna ayuda.
EDITAR : Como señaló Bergi , hay otros objetos posibles que podrían considerarse numéricos y sería mejor incluir en la lista blanca que en la lista negra. Con esto en mente, agregaría a los criterios.
Quiero que mi función isNumeric considere solo números o cadenas
Con esto en mente, sería mejor usar
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(/^-/, ''''));
}
Esto ha sido agregado como prueba 22
En mi opinión, si se trata de una matriz, entonces no es numérica. Para aliviar este problema, agregué un cheque para descontar matrices de la lógica
También puede tener ese problema con cualquier otro objeto, por ejemplo {toString:function(){return "1.2";}}
. ¿Qué objetos crees que son numéricos? Number
objetos? ¿Ninguna?
En lugar de tratar de incluir en la lista negra algunas cosas que no pasaron su prueba, debe incluir explícitamente en la lista blanca las cosas que desea que sean numéricas. ¿Cuál es tu función supuesta para obtener, cadenas y números primitivos? Luego, prueba exactamente para ellos:
(typeof n == "string" || typeof n == "number")
La función isNaN utilizada para verificar el valor es numérica o no. Si los valores son numéricos, su resultado verdadero devuelve falso.
código:
<script>
function IsNumeric(val) {
if (isNaN(parseFloat(val))) {
return false;
}
return true
}
bool IsNumeric(string);
</script>
Qué tal si:
function isNumber(value) {
value = Number(value);
return typeof value === ''number'' && !isNaN(value) && isFinite(value);
}
Si AMD le suena bien, eche un vistazo a isNumber de mout () .
Si está bien que use expresiones regulares, esto podría hacer el truco:
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()));
}
editar: problema resuelto con números hexadecimales
function isNumber(value){
return !isNaN(parseFloat(value)) &&
isFinite(value.toString().replace(/^-/, '''')) &&
typeof value !== ''object'';
}
o:
function isNumber(value){
return !Array.isArray(value) && !isNaN(parseFloat(value)) &&
isFinite(value.toString().replace(/^-/, '''')) &&
Object.prototype.toString.call(value) !== ''[object Object]'';
}
function isNumber(value){return typeof value == ''number'';}