2015-05-18 13 views
23

Ho una variabile x e voglio verificare se x è impostato su NaN. Come lo faccio?Come si esegue il test per NaN in JavaScript?

Il mio primo istinto è probabilmente quello, si sa, testarlo, in questo modo:

if (x === NaN) { ... 

sciocco coniglio, no, sarebbe troppo facile. NaN è come NULL in SQL, non è uguale a niente, nemmeno a se stesso.

Ma guarda, c'è una funzione chiamata isNaN() - forse lo farà!

No, per quanto posso dire, isNaN() è assolutamente inutile.

Ad esempio, isNaN([""]) restituisce correttamente false, ma isNaN(["."]) restituisce true. Non vuoi sapere come ho imparato a conoscere questo difetto.

Come posso fare?

Risulta, la mia domanda è un duplicato di this one, ma la risposta selezionata è errata. Lo right answer ha il 20% di altrettanti di upvotes.

+0

"* Non vuoi sapere come ho imparato a conoscere questo difetto. *" - Mi chiedo perché chiameresti 'isNaN' su un array? – Bergi

+0

@Bergi - Stavo scrivendo un selezionatore di date. Ho quasi preso a pugni lo schermo quando '[" 2015 "," 05 "," 05 "]' è stato contrassegnato come NaN. – Malvolio

+0

Ma perché ti aspetti che un array si comporti come un numero? – Bergi

risposta

15

La domanda ha la risposta se leggi abbastanza da vicino. Questo è il modo in cui l'ho trovato: stavo scrivendo la domanda e ... il bingo.

Ti ricordi quando ho scritto "NaN è come NULL in SQL, non è uguale a niente, anche a se stesso"? Per quanto ne so, NaN è l'unico valore in Javascript con questa proprietà. Pertanto è possibile scrivere:

var reallyIsNaN = function(x) { 
    return x !== x; 
}; 
+0

Dopo aver letto [MDN docs for Number.NaN] (https: // developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN), suggerisce di verificare anche 'typeof x ===" numero "'. 'isNaN' è diverso in quanto costringe il valore a un numero prima di comparare (' + [] == 0', wat?) – thgaskell

+0

@thgaskell Quando dici + [] == 0 ciò che accade è che javascript prova a convertire il valore primo valore dell'array in intero. Prova a chiamare array [0] un un array vuoto e ritornerà indefinito. Questa conversione non è uguale a quella di parseInt e non definito verrà convertito in 0, provare + [1] e + ['1223fsds']. Finalmente 0 == 0. Ecco perché ottieni quel risultato. – devconcept

+0

@devconcept [wat?] (Https://www.youtube.com/watch?v=FqhZZNUyVFM) – thgaskell

27

Risposta breve

Per ECMAScript 5 Utenti:

#1 
if(x !== x) { 
    console.info('x is NaN.'); 
} 
else { 
    console.info('x is NOT a NaN.'); 
} 

Per le persone con ECMAScript-6:

#2 
Number.isNaN(x); 

E per coerenza scopo su ECMAScript 5 & 6 entrambi, è anche possibile utilizzare questo polyfill for Number.isNan

#3 
//Polyfill from MDN 
Number.isNaN = Number.isNaN || function(value) { 
    return typeof value === "number" && isNaN(value); 
} 
// Or 
Number.isNaN = Number.isNaN || function(value) {  
    return value !== value; 
} 

Nota: preferisco testare usando # 1 che funziona lo stesso tutti i luoghi e non ha dipendenza da ultimo JS anche. (Mi dà sempre risultato corretto. Nessuna sorpresa!)


Spiegazione dettagliata:

ecco il nostro impressionante NaN

NaN == NaN; // false 
NaN === NaN; // false 

Si prega di non dare la colpa JavaScript per questo, è NaN che dovrebbe comportarsi in questo anche in altre lingue Che va bene come da rationale for all comparisons returning false NaN values

Così viene isNaN come nostro salvatore, ma aspetta agisce po 'diverso in alcuni scenari, come

isNaN(undefined); // true 
isNaN({});  // true 
isNaN("lorem ipsum"); // true 

ho avuto alcune facce strane vedendo i risultati di cui sopra. E qui viene il motivo da MDN

Quando l'argomento della funzione isNaN non è di tipo Numero, il valore viene prima convertito in un numero. Il valore risultante viene quindi testato per determinare se si tratta di NaN.

Quindi, come dovremmo testare NaN per le variabili non numeriche? Vado sempre dal seguente

if(x !== x) { 
    console.info('Is a NaN'); 
} 
else { 
    console.info('Not a NaN'); 
} 

ECMAScript-6/JavaScript-2015 Aggiornamenti

Abbiamo qualcosa in ECMAScript-6 per lo stesso. Yup che facciamo ...

Number.isNaN(x); // true 

L'implementazione ES6 sarà anche utile per i casi di cui sopra come

Number.isNaN(undefined); // false 
Number.isNaN({}); // false  
Number.isNaN("lorem ipsum"); // false 

mentre ECMAScript-5 funzione globale isNaN uscite in true per i casi di cui sopra, che a volte possono non in linea con le nostre aspettative.

+1

come 'isNaN (" ") = false' e' isNaN ({}) = true' mentre 'Number.isNaN (" ") = false' e' Number.isNaN ({}) = false' – loretoparisi

+0

Polyfill potrebbe anche essere semplice come 'Number ['isNaN'] || (Number.isNaN = function (a) {return a! == a}); 'Fondamentalmente lo stesso, meno una manciata di caratteri e con il set di variabili spostato sull'altro lato dell'operatore. – SpYk3HH

Problemi correlati