¿Por qué isNaN(" ") es igual a false


Tengo una pregunta rápida (¡Espero!). En JS, ¿por qué isNaN(" ") evalúa a false, pero isNaN(" x") evalúa a true?

Estoy realizando operaciones numéricas en un campo de entrada de texto, y estoy comprobando si el campo es null, "", o NaN. Cuando alguien escribe un puñado de espacios en el campo, mi validación falla en los tres, y estoy confundido en cuanto a por qué pasa la verificación de isNaN.

Gracias!

Author: IAdapter, 2009-05-05

22 answers

JavaScript interpreta una cadena vacía como un 0, que luego falla la prueba isNaN. Puede usar parseInt en la cadena primero, lo que no convertirá la cadena vacía a 0. El resultado debe entonces fallar isNaN.

 134
Author: Antonio Haley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-05 15:27:11

Usted puede encontrar esto sorprendente o tal vez no, pero aquí hay un código de prueba para mostrar la locura del motor 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

Así que esto significa que

" " == 0 == false

Y

"" == 0 == false

Pero

"" != " "

Diviértete:)

 71
Author: Nick Berardi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-04 18:16:00

Para entenderlo mejor, abra Ecma-Script spec pdf en la página 43 "ToNumber Applied to the String Type"

Si una cadena tiene una sintaxis numérica, que puede contener cualquier número de caracteres de espacio en blanco, se puede convertir a tipo de número. La cadena vacía se evalúa como 0. También la cadena 'Infinity' debería dar

isNaN('Infinity'); // false
 16
Author: Rafael,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-05 15:32:00

Intenta usar:

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

O

alert(isNaN(parseFloat("    ")));
 15
Author: bendewey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-05 15:27:27

De MDN razón del problema al que se enfrenta

Cuando el argumento de la función isNaN no es de tipo Number, el valor se coacciona primero a un Número. El valor resultante se prueba para determinar si es NaN.

Es posible que desee comprobar la siguiente respuesta completa que cubre la comparación NaN para la igualdad también.

Cómo probar si una variable JavaScript es NaN

 6
Author: dopeddude,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:55:02

Creo que es debido a la escritura de Javascript: ' ' se convierte a cero, mientras que 'x' no lo es:

alert(' ' * 1); // 0
alert('x' * 1); // NaN
 5
Author: Greg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-05 15:27:37

Si desea implementar una función isNumber precisa, aquí hay una forma de hacerlo desde Javascript: Las Partes buenas por Douglas Crockford [página 105]

var isNumber = function isNumber(value) {
   return typeof value === 'number' && 
   isFinite(value);
}
 4
Author: Brian Grinstead,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-05 15:38:23

La Respuesta No del Todo Correcta

La respuesta de Antonio Haley altamente votada y aceptada aquí hace una suposición errónea de que este proceso pasa por la función parseInt de JavaScript:

Puede usar parseInt en la cadena ... El resultado debe entonces fallar isNaN.

Podemos refutar fácilmente esta afirmación con la cadena "123abc":

parseInt("123abc")    // 123     (a number...
isNaN("123abc")       // true     ...which is not a number)

Con esto, podemos ver que la función parseInt de JavaScript devuelve "123abc" como el número 123, aún su función isNaN nos dice que "123abc" no es un número.

La Respuesta Correcta

ECMAScript-262 define cómo funciona la comprobación isNaN en sección 18.2.3.

18.2.3 isNaN (Número)

La función isNaN es el objeto intrínseco %isNaN%. Cuando se llama a la función isNaN con un número de argumento, se siguen los siguientes pasos:

  1. Sea num? ToNumber(number).
  2. Si num es NaN, regresar true.
  3. De lo contrario, devuelve false.

La función ToNumber a la que hace referencia también está definida en La sección 7.1.3 de ECMAScript-262. Aquí, nos dicen cómo JavaScript maneja las cadenas que se pasan a esta función.

El primer ejemplo dado en la pregunta es una cadena que no contiene más que caracteres de espacio en blanco. Esta sección establece que:

Un StringNumericLiteral que está vacío o contiene solo espacio en blanco se convierte en +0.

La cadena de ejemplo " " se convierte entonces a +0, que es un número.

La misma sección también dice:

Si la gramática no puede interpretar el String como una expansión de StringNumericLiteral, entonces el resultado de ToNumber es NaN.

Sin citar todas las comprobaciones contenidas en esa sección, el ejemplo " x" dado en la pregunta cae en la condición anterior, ya que no puede interpretarse como un StringNumericLiteral. " x" es por lo tanto convertido a NaN.

 4
Author: James Donnelly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:48

No estoy seguro de por qué, pero para evitar el problema, siempre puede recortar los espacios en blanco antes de verificar. Probablemente quieras hacer eso de todos modos.

 2
Author: Joel Coehoorn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-05 15:28:00

La función isNaN("") realiza una cadena para Numerar tipo coerción

ECMAScript 3-5 define los siguientes valores de retorno para el operador typeof:

  • indefinido
  • object (null, objects, arrays)
  • booleano
  • número
  • string
  • función

Mejor envolver nuestra prueba en un cuerpo de función:

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

Esta función no está destinada a probar la variable type , sino que prueba el valor coaccionado. Por ejemplo, los booleanos y las cadenas se coaccionan a números, por lo que tal vez desee llamar a esta función como isNumberCoerced()

Si no hay necesidad de probar tipos que no sean string y number , entonces el siguiente fragmento de código podría usarse como parte de alguna condición:

if (!isNaN(s) && s.toString().trim()!='') // 's' can be boolean, number or string
    alert("s is a number")
 2
Author: Steven Pribilinskiy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-13 21:38:09

Le sugiero que use la siguiente función si realmente desea una comprobación adecuada si es un entero:

function isInteger(s)
{
   return Math.ceil(s) == Math.floor(s);
}
 1
Author: Bat_Programmer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-26 09:39:40

Que isNaN(" ") es false es parte del comportamiento confuso de la función global isNaN debido a su coerción de no-números a un tipo numérico.

De MDN:

Desde las primeras versiones de la especificación de la función isNaN, su comportamiento para argumentos no numéricos ha sido confuso. Cuando el argumento de la función isNaN no es de tipo Number, el valor se coacciona primero a un Número. El valor resultante se prueba para determinar si es NaN. Por lo tanto, para los no-números que cuando se coaccionan a tipo numérico dan como resultado un valor numérico no-NaN válido (notablemente la cadena vacía y las primitivas booleanas, que cuando se coaccionan dan valores numéricos cero o uno), el valor devuelto "falso" puede ser inesperado; la cadena vacía, por ejemplo, seguramente "no es un número."

Tenga en cuenta también que con ECMAScript 6, también existe ahora el método Number.isNaN, que según MDN:

En comparación con el global isNaN() function, Number.isNaN() no sufre el problema de convertir forzosamente el parámetro a un número. Esto significa que ahora es seguro pasar valores que normalmente se convertirían a NaN, pero que en realidad no son el mismo valor que NaN. Esto también significa que solo los valores del tipo number, que también son NaN, devuelven true.

Desafortunadamente :

Incluso el método ECMAScript 6 Number.isNaN tiene sus propios problemas, como se describe en la publicación del blog - Arreglando el feo JavaScript y ES6 NaN problema.

 1
Author: lucono,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-29 15:22:11

Como otros explicaron, la función isNaN coaccionará la cadena vacía en un número antes de validarla, cambiando así una cadena vacía en 0 (que es un número válido). Sin embargo, encontré que la función parseInt devolverá NaN cuando intente analizar una cadena vacía o una cadena con solo espacios. Como tal, la siguiente combinación parece estar funcionando bien:

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

Esta comprobación funcionará para números positivos, números negativos y números con un punto decimal, así que lo creo cubre todos los casos numéricos comunes.

 1
Author: Nadav,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-28 03:15:11

Esta función parecía funcionar en mis pruebas

function isNumber(s) {
    if (s === "" || s === null) {
        return false;
    } else {
        var number = parseInt(s);
        if (number == 'NaN') {
            return false;
        } else {
            return true;
        }
    }
}
 0
Author: bruno negrao,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-03 12:41:26

¿Qué pasa con

function isNumberRegex(value) {        
    var pattern = /^[-+]?\d*\.?\d*$/i;
    var match = value.match(pattern);
    return value.length > 0 && match != null;
}
 0
Author: sprinter252,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-12 13:22:57

La función isNaN espera un Número como argumento, por lo que los argumentos de cualquier otro tipo (en su caso una cadena) se convertirán en Número antes de que se realice la lógica de la función real. (Tenga en cuenta que NaN es también un valor de tipo Número!)

Por cierto. esto es común para todas las funciones integradas-si esperan un argumento de cierto tipo, el argumento real se convertirá usando las funciones de conversión estándar. Hay conversiones estándar entre todos los tipos básicos (bool, string, number, object, date, null, undefined.)

La conversión estándar de String a Number se puede invocar explícitamente con Number(). Así que podemos ver que:

  • Number(" ") evalúa a 0
  • Number(" x") evalúa a NaN

Dado esto, el resultado de la función isNaN es completamente lógico!

La verdadera pregunta es por qué la conversión estándar de Cadena a Número funciona como lo hace. La conversión de cadena a número es realmente destinado a convertir cadenas numéricas como "123 "o" 17.5e4 " a los números equivalentes. La conversión primero omite los espacios en blanco iniciales (por lo que "123" es válido) y luego intenta analizar los silencios como un número. Si no se puede analizar como un número ("x" no lo es), entonces el resultado es NaN. Pero existe la regla especial explícita de que una cadena vacía o solo espacios en blanco se convierte a 0. Así que esto explica la conversión.

Referencia: http://www.ecma-international.org/ecma-262/5.1/#sec-9.3.1

 0
Author: JacquesB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-23 09:25:40

Escribí esta pequeña función rápida para ayudar a resolver este problema.

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

Simplemente comprueba si hay caracteres que no sean numéricos (0-9), que no sean '-' o '.', y que no son indefinidos, null o vacío y devuelve true si no hay coincidencias. :)

 0
Author: XtraSimplicity,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-14 00:27:12

El JavaScript la función incorporada isNaN , es - como debería esperarse por defecto - un "Operador de Tipo Dinámico". Por lo tanto, todos los valores que (durante el proceso DTC) pueden producir un verdadero | falso simple como "", " ", " 000", no pueden ser NaN.

Lo que significa que el argumento suministrado primero experimentará una conversión como en:

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

Explicación:

En la línea superior del cuerpo de la función, estamos (primero) tratando de convierta correctamente el argumento en un objeto number. Y (segundo), usando el operador de punto estamos - para nuestra propia conveniencia - despojando inmediatamente, el primitivo valor del objeto creado.

En la segunda línea, estamos tomando el valor obtenido en el paso anterior, y la ventaja del hecho de que NaN no es igual a nada en el universo, ni siquiera a sí mismo, por ejemplo: NaN == NaN >> false para finalmente compararlo (para la desigualdad) con sí mismo.

De esta manera la función return producirá verdadero solo cuando, y solo si, el argumento proporcionado-return, es un intento fallido de conversión a un objeto number, es decir, un número not-a-number; por ejemplo, NaN.


isNaNstatic( )

Sin embargo, para un Operador de Tipo estático - si es necesario y cuando sea necesario - podemos escribir una función mucho más simple como:

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

Y evitar el DTC por completo para que si el argumento no es explícitamente un número NaN, devolverá false. Por lo tanto, la prueba contra lo siguiente:

isNaNStatic(" x"); // will return false porque sigue siendo una cuerda.

Sin embargo: isNaNStatic(1/"x"); // will of course return true. como por ejemplo isNaNStatic(NaN); >> true.

Pero contrariamente a isNaN, el isNaNStatic("NaN"); >> false porque (el argumento) es una cadena ordinaria.

P. S.: La versión estática de isNaN puede ser muy útil en escenarios de codificación modernos. Y puede muy bien ser una de las principales razones por las que me tomé mi tiempo para publicar esto.

Saludos.

 0
Author: Bekim Bacaj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-08 01:01:53

isNAN(<argument>) es una función para decir si el argumento dado es un número ilegal. isNaN tipifica los argumentos en Tipo de número. Si desea comprobar si el argumento es Numérico o no? Utilice la función $.isNumeric() en jQuery.

Es decir, isNaN(foo) es equivalente a isNaN(Número(foo)) Acepta cualquier cadena que tenga todos los números como números por razones obvias. Para ex.

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
 0
Author: Om Sao,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-12 06:32:11

Yo uso esto

    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
 0
Author: kiranvj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-27 12:41:53

NaN !== "no es un número"

NaN es un valor de Tipo Numérico

Esta es una definición de isNaN () en ECMAScript

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

Intente convertir cualquier valor en Número.

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

Si desea determinar si el valor es NaN, primero debe intentar convertirlo en un valor numérico.

 0
Author: Wind West,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-08 10:03:56

Al verificar si cierto valor de cadena con espacios en blanco o " "es isNaN tal vez intente realizar la validación de cadena, ejemplo:

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

 0
Author: Channox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-13 07:07:56