JavaScript: Arbeiten mit NaN (= Not a Number) und dem NaN-Paradoxon
Was ist NaN?
NaN steht für „Not a Number“ – auf Deutsch: „Keine Zahl“. Interessanterweise ist NaN selbst als Zahlenwert in JavaScript definiert. Dieser scheinbare Widerspruch ist der Kern des sogenannten NaN-Paradoxons. NaN ist ein besonderer Wert, der auftritt, wenn eine mathematische Operation keinen sinnvollen Zahlenwert liefern kann.
Die Entstehung von NaN
NaN entsteht in verschiedenen Situationen. Hier die häufigsten:
1. Ungültige mathematische Operationen
let ergebnis = 0 / 0;
console.log(ergebnis); // NaN
let wurzel = Math.sqrt(-1);
console.log(wurzel); // NaN (keine reelle Quadratwurzel aus negativen Zahlen)
2. Fehlgeschlagene Typumwandlungen
let zahl = Number("Hallo");
console.log(zahl); // NaN
let berechnung = 5 * "Welt";
console.log(berechnung); // NaN
3. Operationen mit NaN
let x = NaN;
let ergebnis = x + 5;
console.log(ergebnis); // NaN (NaN infiziert andere Berechnungen)
Die Eigenheiten von NaN
Paradox 1: NaN ist vom Typ Number
Der erste Teil des Paradoxons: NaN ist selbst vom Typ „Number“, obwohl es „Not a Number“ bedeutet.
console.log(typeof NaN); // "number"
Dieser Widerspruch entsteht, weil NaN ein spezieller Wert innerhalb des IEEE 754 Fließkommazahlen-Standards ist. Es repräsentiert einen undefinierten oder nicht darstellbaren Zahlenwert.
Paradox 2: NaN ist mit nichts gleich – nicht einmal mit sich selbst
Das zweite Teil des Paradoxons und wohl die merkwürdigste Eigenschaft: NaN ist der einzige Wert in JavaScript, der nicht mit sich selbst identisch ist.
console.log(NaN === NaN); // false
console.log(NaN == NaN); // false
// Selbst diese Vergleiche funktionieren nicht
console.log(NaN !== NaN); // true (NaN ist nicht gleich NaN!)
Paradox 3: Die einzige wahre Ungleichheit
NaN ist der einzige Wert, für den gleichzeitig gilt:
- x === x ist false
- x !== x ist true
let x = NaN;
console.log(x === x); // false
console.log(x !== x); // true
Für alle anderen Werte in JavaScript ist die erste Aussage immer wahr und die zweite immer falsch.
Paradox 4: Vergleiche mit NaN ergeben immer false
Jeder Vergleich mit NaN ergibt false – selbst wenn man explizit auf Ungleichheit prüft:
console.log(NaN < 1); // false
console.log(NaN > 1); // false
console.log(NaN <= 1); // false
console.log(NaN >= 1); // false
Wie erkennt man NaN?
Da NaN nicht mit sich selbst verglichen werden kann, brauchst du spezielle Methoden, um es zu erkennen.
Die isNaN()-Funktion
Die globale isNaN()
-Funktion prüft, ob ein Wert NaN ist. Achtung: Sie versucht zuerst, den Wert in eine Zahl umzuwandeln.
console.log(isNaN(NaN)); // true
console.log(isNaN(undefined)); // true (weil undefined zu NaN konvertiert wird)
console.log(isNaN("Hallo")); // true (weil "Hallo" nicht zu einer Zahl konvertiert werden kann)
console.log(isNaN("123")); // false (weil "123" zu einer Zahl konvertiert werden kann)
console.log(isNaN(true)); // false (weil true zu 1 konvertiert wird)
Die Number.isNaN()-Methode
Die neuere Number.isNaN()
-Methode ist präziser. Sie prüft, ob ein Wert tatsächlich NaN ist, ohne vorherige Typumwandlung.
console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN(undefined)); // false (undefined ist nicht NaN)
console.log(Number.isNaN("Hallo")); // false (ein String ist nicht NaN)
Der selbst-ungleich Trick
Eine interessante Methode, NaN zu erkennen, nutzt die Eigenschaft, dass es nicht mit sich selbst übereinstimmt:
function istNaN(x) {
return x !== x;
}
console.log(istNaN(NaN)); // true
console.log(istNaN(123)); // false
console.log(istNaN("Hallo")); // false
Dieser Trick funktioniert, weil NaN der einzige Wert ist, der diese Eigenschaft besitzt.
Praktische Auswirkungen des NaN-Paradoxons
Das NaN-Paradoxon kann zu schwer auffindbaren Fehlern führen. Hier einige typische Problemfälle und Lösungen:
Problem 1: Fortpflanzung von NaN in Berechnungen
NaN „infiziert“ weitere Berechnungen:
let eingabe = Number("nicht numerisch");
let summe = 0;
// NaN breitet sich in allen weiteren Berechnungen aus
for (let i = 0; i < 10; i++) {
summe += eingabe;
}
console.log(summe); // NaN, die gesamte Berechnung ist betroffen
Problem 2: Irreführende Vergleiche
let alter = Number(prompt("Wie alt bist du?"));
// Falls der Benutzer "zwanzig" eingibt
if (alter < 18) {
console.log("Du bist minderjährig");
} else {
console.log("Du bist volljährig");
}
// Keiner der Zweige wird ausgeführt, da NaN < 18 false ist und NaN >= 18 auch false ist!
Lösung: NaN immer prüfen und behandeln
let eingabe = prompt("Gib dein Alter ein:");
let alter = Number(eingabe);
if (Number.isNaN(alter)) {
console.log("Das ist keine gültige Zahl!");
} else if (alter < 18) {
console.log("Du bist minderjährig");
} else {
console.log("Du bist volljährig");
}
Arrays und NaN
Das NaN-Paradoxon zeigt sich auch bei der Arbeit mit Arrays:
let zahlen = [1, 2, NaN, 3];
// indexOf findet NaN nicht
console.log(zahlen.indexOf(NaN)); // -1
// includes findet NaN tatsächlich!
console.log(zahlen.includes(NaN)); // true
// filter mit direktem Vergleich funktioniert nicht
console.log(zahlen.filter(zahl => zahl === NaN)); // []
// filter mit Number.isNaN funktioniert
console.log(zahlen.filter(zahl => Number.isNaN(zahl))); // [NaN]
NaN in modernem JavaScript
In modernem JavaScript gibt es einige Wege, besser mit NaN umzugehen:
1. Optional Chaining und Nullish Coalescing
// Verhindere NaN durch Standardwerte
let eingabe = Number(benutzerEingabe || "0");
// Oder besser mit Nullish Coalescing (??), das nur bei null/undefined einspringt
let sichereEingabe = Number(benutzerEingabe ?? "0");
2. Destructuring mit Standardwerten
// Extrahiere Zahlen aus Objekten mit Standardwerten
const { alter = 0 } = benutzer;
3. Array-Methoden zum Umgang mit NaN
const zahlen = [1, 2, NaN, 3, NaN];
// Entferne alle NaN-Werte
const bereinigteMenge = zahlen.filter(zahl => !Number.isNaN(zahl));
console.log(bereinigteMenge); // [1, 2, 3]
Praktische Tipps zum Umgang mit NaN
- Eingaben immer prüfen: Validiere Benutzereingaben, bevor du sie in Zahlen umwandelst.
function istGültigeZahl(eingabe) {
return !isNaN(parseFloat(eingabe)) && isFinite(eingabe);
}
- Default-Werte verwenden: Setze vernünftige Standardwerte, falls NaN auftritt.
let alter = Number(eingabe);
if (Number.isNaN(alter)) {
alter = 0; // Standardwert
}
- Früh scheitern: Prüfe auf NaN am Anfang einer Funktion und gib früh einen Fehler zurück.
function berechneRabatt(preis, prozentsatz) {
if (Number.isNaN(preis) || Number.isNaN(prozentsatz)) {
throw new Error("Ungültige Zahlen für die Rabattberechnung");
}
return preis * (prozentsatz / 100);
}
- Verwende spezialisierte Hilfsfunktionen: Erstelle Funktionen, die NaN-Werte erkennen und behandeln.
function sichereAddition(a, b) {
if (Number.isNaN(a) || Number.isNaN(b)) {
return 0; // oder einen anderen Standardwert
}
return a + b;
}
Zusammenfassung
Das NaN-Paradoxon in JavaScript beschreibt mehrere merkwürdige Eigenschaften eines speziellen Zahlenwerts:
- NaN ist ein Zahlenwert, der „Keine Zahl“ bedeutet.
- NaN ist nicht gleich sich selbst.
- NaN infiziert alle nachfolgenden Berechnungen.
- NaN erfordert spezielle Erkennungsmethoden.
Diese Eigenheiten machen NaN zu einem wichtigen Konzept, das du verstehen musst, um robuste JavaScript-Programme zu schreiben. Mit den richtigen Techniken kannst du das NaN-Paradoxon meistern und damit verbundene Probleme vermeiden.