Este código en JS me da una ventana emergente que dice "Creo que nulo es un número", lo 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:
console.log(null == NaN); // false
console.log(isNaN("text")); // true
console.log(NaN == "text"); // false
Entonces, ¿el problema parece no 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é fue:
- Se eliminó una nota que decía que había arruinado el titular en primer lugar al revertir su significado
- Las respuestas anteriores mostraron que no dije con suficiente claridad por qué pensaba que el comportamiento era extraño, así que agregué los ejemplos que verifican una cadena y hacen una comparación manual.
javascript
Hanno Fietz
fuente
fuente
Respuestas:
Creo que el código está tratando de preguntar, "¿es
x
numérico?" con el caso específico aquí dex = null
. La funciónisNaN()
se puede usar para responder esta pregunta, pero semánticamente se refiere específicamente al valorNaN
. De Wikipedia paraNaN
:En la mayoría de los casos, pensamos que la respuesta a "¿es numérico nulo?" debería ser no. Sin embargo,
isNaN(null) == false
es semánticamente correcto, porquenull
no lo esNaN
.Aquí está la explicación algorítmica:
La función
isNaN(x)
intenta convertir el parámetro pasado a un número 1 (equivalente aNumber(x)
) y luego prueba si el valor esNaN
. 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ámetrox
a un número resultaNaN
, devuelve verdadero; de lo contrario, devuelve falso.Entonces, en el caso específico
x = null
,null
se convierte al número 0, (intente evaluarNumber(null)
y ver que devuelve 0,) yisNaN(0)
devuelve falso. Una cadena que solo tiene dígitos puede convertirse en un número e isNaN también devuelve falso. Una cadena (p'abcd'
. Ej. ) Que no se puede convertir a un número haráisNaN('abcd')
que devuelva verdadero, específicamente porqueNumber('abcd')
devuelveNaN
.Además de estos casos extremos aparentes, hay razones numéricas estándar para devolver NaN como 0/0.
En cuanto a las pruebas de igualdad aparentemente inconsistentes que se muestran en la pregunta, el comportamiento de
NaN
se especifica de modo que cualquier comparaciónx == NaN
sea falsa, independientemente del otro operando, incluido élNaN
mismo 1 .fuente
NaN !== NaN
. Entonces, creo que no es totalmente correcto decirloNumber('abcd') == NaN
porqueNumber('abcd')
esNaN
pero no igual aNaN
. Adoro JavaScript.Number('abcd')
esNaN
, pero he dado a entender que prueba verdadera de la igualdad, que no es el caso. Lo editaréisNaN
y estánNumber
diseñados para comportarse de esa manera.null
a0
solo (al menos en este contexto) ocurre dentro de laisNaN()
función, que coacciona su argumento.Me encontré con este problema yo mismo.
Para mí, la mejor manera de usar isNaN es así
isNaN(parseInt(myInt))
tomando el ejemplo de phyzome de arriba,
(Alineé el resultado de acuerdo con la entrada, espero que sea más fácil de leer).
Esto me parece mejor.
fuente
myInt
= "123d".parseInt
convierte "123d" a 123, que luego falla laisNaN
prueba.isNaN(parseInt(str,10)) || isNaN(Number())
. por cierto, para mí, ya que tengo que ejecutarparseInt
para usar el valor numérico de la cadena, lo que permite que "123d" sea considerado como un número válido está bien. Sin embargo, veo la necesidad de detectar ese escenario también.(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. Su especificación para isNan:
La sección 9.3 especifica el comportamiento de
ToNumber
(que no es una función invocable, sino un componente del sistema de conversión de tipos). Para resumir la tabla, ciertos tipos de entrada pueden producir un NaN. Estos son tipoundefined
, tiponumber
(pero solo el valorNaN
), cualquier objeto cuya representación primitiva seaNaN
, y cualquier objetostring
que no pueda analizarse. Este hojasundefined
,NaN
,new Number(NaN)
, y la mayoría de las cadenas.Cualquier entrada de este tipo que se produzca
NaN
como salida cuando se pase aToNumber
producirá untrue
cuando se alimente aisNaN
. Comonull
puede convertirse con éxito en un número, no producetrue
.Y es por eso.
fuente
Esto es realmente inquietante. Aquí hay una serie de valores que probé:
Evalúa (en la consola Firebug) para:
Cuando llamo
x.map(isNaN)
(para llamar a isNaN en cada valor), obtengo:En conclusión, ¡
isNaN
parece bastante inútil! ( Editar : excepto que resulta que isNaN solo se define sobre Number, en cuyo caso funciona bien, solo con un nombre engañoso).Por cierto, aquí están los tipos de esos valores:
fuente
Nulo no es NaN, así como una cadena no es NaN. isNaN () solo prueba si realmente tienes el objeto NaN.
fuente
No estoy exactamente seguro cuando se trata de JS, pero he visto cosas similares en otros idiomas y generalmente es porque la función solo está verificando si nulo es exactamente igual a NaN (es decir, nulo === NaN sería falso). En otras palabras, no es que piense que nulo es de hecho un número, sino que nulo no es NaN. Esto se debe probablemente a que ambos están representados de manera diferente en JS para que no sean exactamente iguales, de la misma manera que 9! == '9'.
fuente
En ES5, se define como
isNaN (number)
devuelve verdadero si el argumento coacciona a NaN, y de lo contrario devuelve falso.Y vea la tabla de conversión La operación abstracta ToNumber . Entonces, internamente, la evaluación del motor js
ToNumber(Null)
es+0
, luego eventualmenteisNaN(null)
esfalse
fuente
Nota:
El operador == realiza conversión de tipo, mientras que === no.
El sitio web de Douglas Crockford , un Yahoo! Evangelista de JavaScript, es un gran recurso para cosas como esta.
fuente