ejemplos - javascript html
¿Por qué isNaN(null)== falso en JS? (8)
Este código en JS me da una ventana emergente que dice "creo que null es un número", que me parece un poco inquietante. ¿Qué me estoy perdiendo?
if (isNaN(null)) {
alert("null is not a number");
} else {
alert("i think null is a number");
}
Estoy usando Firefox 3. ¿Es eso un error del navegador?
Otras pruebas:
null == NaN; // false
isNaN("text"); // true
NaN == "text" // false
Entonces, ¿el problema no parece ser una comparación exacta con NaN?
Editar: ahora que la pregunta ha sido respondida, he limpiado mi publicación para tener una mejor versión para el archivo. Sin embargo, esto hace que algunos comentarios e incluso algunas respuestas sean un poco incomprensibles. No culpes a sus autores. Entre las cosas que cambié estaba:
- Se eliminó una nota que decía que había arruinado el título al revirtir su significado
- Las respuestas anteriores mostraron que no dije con suficiente claridad por qué pensé que el comportamiento era extraño, así que agregué los ejemplos que verifican una cadena y hacen una comparación manual.
(Mi otro comentario tiene un enfoque práctico. Aquí está el lado teórico).
Busqué el estándar ECMA 262 , que es lo que implementa Javascript. Sus especificaciones para isNan:
Aplica ToNumber a su argumento, luego devuelve verdadero si el resultado es NaN, y devuelve falso.
La Sección 9.3 especifica el comportamiento de ToNumber
(que no es una función invocable, sino más bien un componente del sistema de conversión de tipo). Para resumir la tabla, ciertos tipos de entrada pueden producir un NaN. Estos son tipo undefined
, tipo number
(pero solo el valor NaN
), cualquier objeto cuya representación primitiva es NaN
, y cualquier string
que no puede ser analizada. Esto deja undefined
, NaN
, new Number(NaN)
y la mayoría de las cadenas.
Cualquier entrada de ese tipo que produzca NaN
como salida cuando se pase a ToNumber
generará un true
cuando se alimente a isNaN
. Como null
puede convertirse con éxito en un número, no produce true
.
Y es por eso.
Creo que el código está tratando de preguntar: "¿es x
numérico?" con el caso específico aquí de x = null
. La función isNaN()
se puede usar para responder a esta pregunta, pero semánticamente se refiere específicamente al valor NaN
. De Wikipedia para NaN
:
NaN ( N ot a N umber) es un valor del tipo de datos numéricos que representa un valor indefinido o irrepresentable, especialmente en cálculos de coma flotante.
En la mayoría de los casos creemos que la respuesta a "¿es nulo?" debería ser no. Sin embargo, isNaN(null) == false
es semánticamente correcto, porque null
no es NaN
.
Aquí está la explicación algorítmica:
La función isNaN(x)
intenta convertir el parámetro pasado a un número 1 (equivalente a Number(x)
) y luego prueba si el valor es NaN
. Si el parámetro no se puede convertir a un número, Number(x)
devolverá NaN
2 . Por lo tanto, si la conversión del parámetro x
a un número da como resultado NaN
, devuelve verdadero; de lo contrario, devuelve falso.
Entonces en el caso específico x = null
, null
se convierte al número 0, (intente evaluar Number(null)
y vea que devuelve 0,) e isNaN(0)
devuelve false. Una cadena que solo tiene dígitos se puede convertir a un número e isNaN también devuelve falso. Una cadena (por ejemplo, ''abcd''
) que no se puede convertir a un número hará que isNaN(''abcd'')
devuelva verdadero, específicamente porque Number(''abcd'')
devuelve NaN
.
Además de estos casos de borde aparente son las razones numéricas estándar para devolver NaN como 0/0.
En cuanto a las aparentemente inconsistentes pruebas de igualdad que se muestran en la pregunta, el comportamiento de NaN
se especifica de tal manera que cualquier comparación x == NaN
es falsa, independientemente del otro operando, incluido el propio NaN
1 .
En ES5, se define como isNaN (number)
devuelve verdadero si el argumento coacciona a NaN, y de lo contrario devuelve falso.
- Si ToNumber(number) es NaN, devuelve true.
- De lo contrario, devuelve falso.
Y vea la ToNumber(number) . Entonces, internamente, el motor js evalúa ToNumber(Null)
es +0
, luego eventualmente isNaN(null)
es false
Esto es ciertamente perturbador. Aquí hay una matriz de valores que probé:
var x = [undefined, NaN, ''blah'', 0/0, null, 0, ''0'', 1, 1/0, -1/0, Number(5)]
Evalúa (en la consola Firebug) a:
,NaN,blah,NaN,,0,0,1,Infinity,-Infinity,5
Cuando llamo a x.map(isNaN)
(para llamar a isNaN en cada valor), obtengo:
true,true,true,true,false,false,false,false,false,false,false
En conclusión, isNaN
parece bastante inútil! ( Editar : Excepto que resulta queNaN solo está definido en Número, en cuyo caso funciona perfectamente, solo que con un nombre engañoso).
Por cierto, aquí están los tipos de esos valores:
x.map(function(n){return typeof n})
-> undefined,number,string,number,object,number,string,number,number,number,number
Me encontré con este problema yo mismo.
Para mí, la mejor manera de usar isNaN es como
isNaN(parseInt(myInt))
tomando el ejemplo de phyzome desde arriba,
var x = [undefined, NaN, ''blah'', 0/0, null, 0, ''0'', 1, 1/0, -1/0, Number(5)]
x.map( function(n){ return isNaN(parseInt(n))})
[true, true, true, true, true, false, false, false, true, true, false]
(Alineé el resultado de acuerdo con la entrada, espero que sea más fácil de leer).
Esto me parece mejor.
No estoy exactamente seguro cuando se trata de JS pero he visto cosas similares en otros lenguajes y generalmente es porque la función solo está comprobando si null es exactamente igual a NaN (es decir, nulo === NaN sería falso). En otras palabras, no es que piense que null es de hecho un número, sino que es nulo no es NaN. Esto es probablemente porque ambos están representados de manera diferente en JS para que no sean exactamente iguales, de la misma manera que 9! == ''9''.
Nota:
"1" == 1 // true
"1" === 1 // false
El operador == realiza una conversión de tipo, mientras que === no.
Sitio web de Douglas Crockford , Yahoo! El evangelista de JavaScript es un gran recurso para cosas como esta.
Null no es NaN, y una cadena no es NaN. isNaN () simplemente prueba si realmente tienes el objeto NaN.