Gestire NaN, Infinity e i numeri speciali in JavaScript

by Anastasia P.
SHARE
Gestire NaN, Infinity e i numeri speciali in JavaScript
© Guida-HTML5.it

Introduzione

Quando si lavora con le variabili JavaScript e con il tipo primitivo number, non si incontrano soltanto numeri interi e decimali. Il linguaggio include anche alcuni valori speciali: NaN, Infinity e -Infinity. Comprenderli è importante per evitare bug nei calcoli, nei form e nelle applicazioni che elaborano dati provenienti da utenti o API.

Il valore NaN significa “Not a Number”, cioè “non è un numero”. Il nome può essere fuorviante: in JavaScript, infatti, typeof NaN restituisce "number". Questo accade perché NaN appartiene comunque all’insieme dei valori numerici gestiti dal linguaggio, anche se rappresenta un risultato numerico non valido.

Infinity rappresenta un valore numerico infinito. Può essere ottenuto, per esempio, dividendo un numero positivo per zero. Un numero negativo diviso per zero produce invece -Infinity. Questi valori possono propagarsi nei calcoli e generare risultati inattesi se non vengono controllati.

Codice completo

// Dati ricevuti, ad esempio, da un campo di un modulo
const prezzoInserito = "19.99";
const quantitaInserita = "3";
const scontoInserito = "abc";

// Conversione esplicita delle stringhe in numeri
const prezzo = Number(prezzoInserito);
const quantita = Number(quantitaInserita);
const sconto = Number(scontoInserito);

// Controlliamo se ogni valore è un numero finito e utilizzabile
function numeroValido(valore) {
  return typeof valore === "number" && Number.isFinite(valore);
}

console.log(numeroValido(prezzo));   // true
console.log(numeroValido(quantita)); // true
console.log(numeroValido(sconto));   // false, sconto è NaN

// Calcolo sicuro del totale
if (!numeroValido(prezzo) || !numeroValido(quantita)) {
  console.error("Prezzo o quantità non validi.");
} else if (quantita < 0) {
  console.error("La quantità non può essere negativa.");
} else {
  const totale = prezzo * quantita;
  console.log(`Totale: ${totale.toFixed(2)} €`);
}

// Esempi di valori speciali
const risultatoNonNumerico = 0 / 0;
const infinitoPositivo = 10 / 0;
const infinitoNegativo = -10 / 0;

console.log(risultatoNonNumerico); // NaN
console.log(infinitoPositivo);     // Infinity
console.log(infinitoNegativo);     // -Infinity

// Controlli specifici
console.log(Number.isNaN(risultatoNonNumerico)); // true
console.log(Number.isFinite(infinitoPositivo));   // false
console.log(Number.isFinite(250));                // true

// Attenzione: il confronto diretto con NaN non funziona
console.log(risultatoNonNumerico === NaN); // false

Spiegazione

Come nasce NaN

NaN può comparire quando un’operazione non produce un risultato numerico valido. Un caso comune è la conversione di una stringa non numerica:

const valore = Number("ciao");

console.log(valore); // NaN
console.log(typeof valore); // "number"

Può comparire anche in operazioni matematiche non definite, come 0 / 0, oppure quando si tenta di eseguire calcoli su valori già non validi. Una caratteristica fondamentale di NaN è che non è uguale nemmeno a sé stesso. Per questo motivo il controllo corretto è Number.isNaN(valore), non valore === NaN.

Perché usare Number.isFinite

Number.isFinite() verifica che il valore sia effettivamente un numero finito. Restituisce false per NaN, Infinity, -Infinity e per valori di altri tipi, come le stringhe.

console.log(Number.isFinite(42));       // true
console.log(Number.isFinite(NaN));      // false
console.log(Number.isFinite(Infinity)); // false
console.log(Number.isFinite("42"));     // false

Questo comportamento è più sicuro rispetto alla funzione globale isFinite(), che tenta una conversione implicita:

console.log(isFinite("42"));           // true
console.log(Number.isFinite("42"));    // false

Se stiamo validando dati provenienti dall’esterno, è preferibile usare Number.isFinite() dopo una conversione esplicita e consapevole.

Infinity nei calcoli

Infinity può essere prodotto da una divisione per zero oppure da un calcolo che supera i limiti pratici rappresentabili. Una volta ottenuto, può influenzare altre operazioni:

const valore = Infinity;

console.log(valore + 100); // Infinity
console.log(valore * 0);   // NaN
console.log(valore > 1000000); // true

È quindi utile controllare che un risultato sia finito prima di salvarlo, visualizzarlo o inviarlo a un server.

Best practice

  • Usa Number.isNaN() per verificare esclusivamente la presenza di NaN.
  • Usa Number.isFinite() quando un valore deve essere un numero reale e finito.
  • Evita di confrontare NaN con l’operatore ===: il confronto restituisce sempre false.
  • Converti esplicitamente i dati esterni con Number(), invece di affidarti a conversioni automatiche.
  • Controlla anche i vincoli del dominio: un numero può essere finito, ma comunque non valido, come una quantità negativa.
  • Non usare soltanto typeof valore === "number": questo controllo considera validi anche NaN e Infinity.
  • Valida i risultati subito dopo un calcolo importante, prima di passarli ad altre funzioni.

Una funzione di validazione può includere anche regole specifiche dell’applicazione:

function prezzoValido(prezzo) {
  return Number.isFinite(prezzo) && prezzo >= 0;
}

console.log(prezzoValido(12.50)); // true
console.log(prezzoValido(-5));    // false
console.log(prezzoValido(NaN));   // false

Riepilogo

JavaScript tratta NaN, Infinity e -Infinity come valori del tipo primitivo number, ma non come normali numeri utilizzabili in ogni contesto. NaN indica un risultato non numerico, mentre Infinity rappresenta un valore infinito ottenuto, spesso, da una divisione per zero o da un calcolo fuori scala.

Per scrivere codice affidabile, bisogna distinguere tra il semplice controllo del tipo e la verifica del contenuto. typeof può confermare che un valore appartiene al tipo number, ma Number.isFinite() è più adatto per stabilire se il valore è realmente utilizzabile. Quando serve individuare proprio NaN, si usa Number.isNaN().

Approfondisci con risorse ufficiali

SHARE