Die `Number`-Klasse in JavaScript

Die `Number`-Klasse in JavaScript

Dieser Artikel erklärt die Number-Klasse in JavaScript.

Wir erklären sorgfältig die Eigenschaften von Number, häufige Fallstricke, nützliche APIs und praktische Beispiele Schritt für Schritt.

YouTube Video

Die Number-Klasse in JavaScript

Number ist der grundlegende numerische Typ in JavaScript und wird als IEEE-754 Gleitkommazahl mit doppelter Genauigkeit (64 Bit) dargestellt.

Grundlagen: Zahlenrepräsentation und Typüberprüfung

In JavaScript werden alle Zahlen als primitiver Typ number dargestellt.

 1// Primitive numbers and Number object
 2const a = 42;                 // primitive number
 3const b = 3.14;               // primitive float
 4const c = Number(10);         // primitive via constructor call (function form)
 5const d = new Number(10);     // Number object (wrapper)
 6
 7console.log(typeof a);        // "number"
 8console.log(typeof d);        // "object"
 9console.log(c == d);          // true  (value coerces)
10console.log(c === d);         // false (different types)
  • Dieser Code demonstriert den Unterschied zwischen einer primitiven number und dem Number-Wrapper-Objekt. Normalerweise werden Primitive anstelle von Wrappern verwendet.

Sonderwerte: NaN, Infinity und Konstanten

Number stellt Sonderwerte (NaN, Infinity) und Konstanten bereit.

 1// Special numeric values and constants
 2console.log(Number.NaN);                 // NaN
 3console.log(Number.POSITIVE_INFINITY);   // Infinity
 4console.log(Number.NEGATIVE_INFINITY);   // -Infinity
 5
 6console.log(Number.MAX_VALUE);           // largest positive representable
 7console.log(Number.MIN_VALUE);           // smallest positive representable (closest to 0)
 8console.log(Number.MAX_SAFE_INTEGER);    // 9007199254740991
 9console.log(Number.MIN_SAFE_INTEGER);    // -9007199254740991
10console.log(Number.EPSILON);             // smallest difference ~2.220446049250313e-16
  • Ganzzahlen größer oder gleich MAX_SAFE_INTEGER können möglicherweise nicht exakt dargestellt werden. Verwenden Sie BigInt, wenn Genauigkeit erforderlich ist. EPSILON wird für Gleitkommavergleiche verwendet.

Zahlenumwandlung: Number(), parseInt, parseFloat und das +-Operator

Es gibt mehrere Möglichkeiten, einen String in eine Zahl umzuwandeln, jede davon mit unterschiedlichem Verhalten.

 1// Converting strings to numbers
 2console.log(Number("42"));        // 42
 3console.log(Number("  3.14 "));   // 3.14
 4console.log(+ "7");               // 7 (unary +)
 5
 6console.log(parseInt("42px"));    // 42
 7console.log(parseFloat("3.14abc"));// 3.14
 8
 9// Careful with parseInt and radix
10console.log(parseInt("08"));      // 8
11console.log(parseInt("08", 10));  // 8 (explicit radix is safer)
  • Number() gibt NaN zurück, sofern der gesamte String nicht streng numerisch ist, während parseInt und parseFloat den lesbaren Zahlenteil ab dem Anfang des Strings parsen. Es ist sicherer, beim Verwenden von parseInt immer explizit das Zahlensystem (radix) anzugeben.

Behandlung und Überprüfung von NaN: isNaN und Number.isNaN

NaN (Not-A-Number) ist besonders, weil NaN !== NaN gilt. Es gibt Unterschiede bei der Überprüfung; das globale isNaN führt eine Typumwandlung durch und kann zu Fehlalarmen führen, daher wird Number.isNaN empfohlen.

1// NaN detection differences
2console.log(NaN === NaN);             // false
3
4console.log(isNaN("foo"));            // true  -> because "foo" coerces to NaN
5console.log(Number.isNaN("foo"));     // false -> "foo" is not the numeric NaN
6
7console.log(Number.isNaN(NaN));       // true
  • Nutzen Sie Number.isNaN, um Zahlen zu überprüfen und Ergebnisse zu validieren, um unnötige Typkonvertierungen zu vermeiden.

Gleitkommafehler und Vergleiche mit Number.EPSILON

Aufgrund von IEEE-754 treten Fehler wie 0.1 + 0.2 !== 0.3 auf. Für genaue Vergleiche verwendet man üblicherweise die Differenz und Number.EPSILON.

1// Floating point precision example and EPSILON comparison
2const sum = 0.1 + 0.2;
3console.log(sum === 0.3);             // false
4
5function nearlyEqual(a, b, epsilon = Number.EPSILON) {
6  return Math.abs(a - b) <= epsilon * Math.max(1, Math.abs(a), Math.abs(b));
7}
8
9console.log(nearlyEqual(sum, 0.3));   // true
  • Wenn Fehler beim Vergleich zugelassen werden, empfiehlt sich eine robuste Implementierung wie nearlyEqual, die sowohl Skalierung als auch absolute Differenzen berücksichtigt.

Überprüfung auf Ganzzahlen und sichere Ganzzahlen (isInteger, isSafeInteger)

Es gibt APIs, um zu überprüfen, ob ein Wert eine Ganzzahl ist und innerhalb des sicheren Bereichs liegt.

1// Integer and safe integer checks
2console.log(Number.isInteger(3));                 // true
3console.log(Number.isInteger(3.0));               // true
4console.log(Number.isInteger(3.1));               // false
5
6console.log(Number.isSafeInteger(Number.MAX_SAFE_INTEGER)); // true
7console.log(Number.isSafeInteger(Number.MAX_SAFE_INTEGER + 1)); // false
  • Wenn Genauigkeit bei großen Ganzzahlen erforderlich ist, verwenden Sie Number.isSafeInteger und erwägen Sie für größere Zahlen den Einsatz von BigInt.

Anzeige und Formatierung: toFixed, toPrecision, toString

Es stehen Methoden zur Verfügung, um die Anzeige von Zahlen zu steuern. toFixed gibt einen String mit der angegebenen Anzahl von Nachkommastellen zurück, aber beim Runden ist Vorsicht geboten.

1// Formatting numbers for display
2const x = 1.23456;
3console.log(x.toFixed(2));         // "1.23"   (string)
4console.log(x.toPrecision(3));     // "1.23"   (string with total significant digits)
5console.log((255).toString(16));   // "ff"     (hexadecimal string)
  • toFixed gibt einen String zurück, daher sollte man achten, wenn man ihn für Berechnungen in eine Zahl umwandelt.

Vorsicht bei Zeichenkettenverkettung und dem +-Operator

Der +-Operator wird sowohl für die numerische Addition als auch für die Zeichenkettenverkettung verwendet, daher können je nach beteiligten Datentypen unerwartete Ergebnisse entstehen.

1// Pitfall with + operator and type coercion
2console.log(1 + 2 + "px");    // "3px"
3console.log("px" + 1 + 2);    // "px12"
4console.log(1 + "2" - 0);     // 3  (string coerced to number for subtraction)
  • Wenn Strings und Zahlen gemischt werden, ist es sicherer, explizit String(), Number() oder Template-Literals zu verwenden, um implizite Typkonvertierungen zu vermeiden.

Erweiterte Anwendungsfälle: Number.parseInt / Number.parseFloat, valueOf

Number.parseInt und Number.parseFloat sind Aliasnamen der globalen Funktionen. valueOf wird verwendet, um den primitiven Wert aus einem Number-Objekt zu extrahieren, wird aber in der Praxis selten benötigt.

1// Number.parseInt/parseFloat aliases and valueOf example
2console.log(Number.parseInt("100", 10));   // 100
3console.log(Number.parseFloat("3.14"));    // 3.14
4
5const nObj = new Number(5);
6console.log(nObj.valueOf());               // 5
7console.log(nObj + 1);                     // 6  (object coerced to primitive)
  • Beim Verwenden von Number.parseInt und Number.parseFloat ist auf das Zahlensystem (radix) und die Bereinigung der Eingabe zu achten. Wrapper-Objekte werden üblicherweise vermieden.

Referenz: Kleines Dienstprogrammbeispiel – Zahlenvalidierungsfunktionen

Hier sind kleine Hilfsfunktionen, die häufig verwendete Überprüfungen zusammenfassen. Dadurch werden Aufgaben wie die Eingabevalidierung erleichtert.

 1// Small number utility functions
 2function toNumberStrict(value) {
 3  // Return a Number or throw for invalid numeric strings
 4  const n = Number(value);
 5  if (typeof value === "string" && value.trim() === "") {
 6    throw new Error("Empty string is not a valid number");
 7  }
 8  if (Number.isNaN(n)) {
 9    throw new Error(`Invalid number: ${value}`);
10  }
11  return n;
12}
13
14function almostEqual(a, b, eps = Number.EPSILON) {
15  // Robust relative comparison
16  return Math.abs(a - b) <= eps * Math.max(1, Math.abs(a), Math.abs(b));
17}
  • Dies sind sehr vielseitige Funktionen, die wiederholt für Eingabeverarbeitung und Vergleiche genutzt werden können. Implementierungen, die Fehler auslösen, sind für Validierungszwecke nützlich.

Zusammenfassung: Performance und bewährte Praktiken

Folgende praktische Punkte sind bei der Verwendung von Number zu beachten.

  • Grundsätzlich sollte man den primitiven Typ number verwenden und new Number() vermeiden.
  • Wählen Sie je nach Anwendungsfall zwischen Number() (streng) oder parseInt/parseFloat (partielles Auslesen) für die String-zu-Zahl-Umwandlung.
  • Verwenden Sie Number.isNaN und Number.isFinite für sichere Überprüfungen.
  • Für Gleitkommavergleiche verwenden Sie Number.EPSILON oder eine eigene Vergleichsfunktion.
  • Wenn Genauigkeit bei Ganzzahlen erforderlich ist, verwenden Sie Number.isSafeInteger, und verwenden Sie BigInt, falls der Wertebereich überschritten wird.
  • Sie können toFixed oder toPrecision zum Runden bei der Anzeige verwenden, aber beachten Sie, dass der Rückgabewert ein String ist.

Zusammenfassung

Number ist der Basistyp für alle Zahlen in JavaScript, einschließlich Ganzzahlen, Dezimalzahlen und Sonderwerten (NaN und Infinity). Es ist wichtig, auf Typkonvertierungen und Gleitkommafehler zu achten und Methoden wie Number.isNaN und Number.EPSILON korrekt zu verwenden. Wenn der sichere Ganzzahlenbereich überschritten wird, verwenden Sie BigInt und für Rundung und Anzeige toFixed oder toPrecision.

Sie können den obigen Artikel mit Visual Studio Code auf unserem YouTube-Kanal verfolgen. Bitte schauen Sie sich auch den YouTube-Kanal an.

YouTube Video