De `Number`-klasse in JavaScript

De `Number`-klasse in JavaScript

Dit artikel legt de Number-klasse in JavaScript uit.

We leggen stap voor stap de kenmerken van Number, veelvoorkomende valkuilen, nuttige APIs en praktische voorbeelden uit.

YouTube Video

De Number-klasse in JavaScript

Number is het fundamentele numerieke type in JavaScript en wordt weergegeven als een IEEE-754 dubbelprecisie drijvendekomma (64-bits).

Basis: Nummerweergave en type-controle

In JavaScript worden alle getallen weergegeven als het primitieve number-type.

 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)
  • Deze code toont het verschil aan tussen een primitieve number en het Number wrapper-object. Normaal gesproken worden primitieven gebruikt in plaats van wrappers.

Speciale waarden: NaN, Infinity en constanten

Number biedt speciale waarden (NaN, Infinity) en constanten.

 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
  • Gehele getallen die groter zijn dan of gelijk aan MAX_SAFE_INTEGER kunnen mogelijk niet nauwkeurig worden weergegeven. Overweeg BigInt te gebruiken als nauwkeurigheid vereist is. EPSILON wordt gebruikt voor drijvendekomma-vergelijkingen.

Nummerconversie: Number(), parseInt, parseFloat en de +-operator

Er zijn verschillende manieren om een tekenreeks naar een getal te converteren, elk met verschillende gedrag.

 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() retourneert NaN, tenzij de hele string strikt in numeriek formaat is, terwijl parseInt en parseFloat het leesbare numerieke deel vanaf het begin van de string parseren. Het is veiliger om altijd expliciet het talstelsel (radix) op te geven bij gebruik van parseInt.

Omgaan met en controleren op NaN: isNaN en Number.isNaN

NaN (Not-A-Number) is bijzonder omdat NaN !== NaN. Er zijn verschillen in hoe ze controleren; de globale isNaN doet typeconversie en kan leiden tot foutieve resultaten, dus Number.isNaN wordt aanbevolen.

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
  • Gebruik Number.isNaN voor het controleren van getallen en het valideren van berekeningen om onnodige typeconversies te voorkomen.

Fouten met drijvendekomma en vergelijkingen met behulp van Number.EPSILON

Door IEEE-754 treden fouten op zoals 0.1 + 0.2 !== 0.3. Voor strikte vergelijkingen wordt vaak het verschil met Number.EPSILON gebruikt.

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
  • Als fouten bij vergelijkingen zijn toegestaan, wordt een robuuste implementatie zoals nearlyEqual, die ook schaling en absolute verschillen gebruikt, aanbevolen.

Controleren op gehele getallen en veilige gehele getallen (isInteger, isSafeInteger)

Er zijn APIs om te controleren of een waarde een geheel getal is en of deze binnen het veilige bereik valt.

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
  • Als nauwkeurigheid bij grote getallen nodig is, gebruik dan Number.isSafeInteger en overweeg BigInt voor getallen buiten dat bereik.

Weergave en opmaak: toFixed, toPrecision, toString

Er zijn methoden beschikbaar om de weergave van getallen te regelen. toFixed retourneert een tekenreeks met een opgegeven aantal decimalen, maar let op afrondingen.

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 retourneert een string, dus let op de waarden nadat ze zijn omgezet naar getallen voor berekeningen.

Let op met tekenreeksconcatenatie en de +-operator

De +-operator wordt gebruikt voor zowel numerieke optelling als voor tekenreeksconcatenatie, wat tot onverwachte resultaten kan leiden afhankelijk van de gebruikte datatypes.

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)
  • Wanneer tekenreeksen en getallen worden gemengd, is het veiliger om expliciet String(), Number() of template literals te gebruiken om impliciete typeconversie te voorkomen.

Geavanceerde toepassingen: Number.parseInt / Number.parseFloat, valueOf

Number.parseInt en Number.parseFloat zijn aliassen van de globale functies. valueOf wordt gebruikt om de primitieve waarde van een Number-object op te halen, maar dit is zelden nodig in de praktijk.

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)
  • Bij het gebruik van Number.parseInt en Number.parseFloat, wees voorzichtig met het talstelsel (radix) en het bijsnijden van de invoer. Wrapperobjecten worden meestal vermeden.

Referentie: Klein hulpprogramma - Functies voor getalvalidatie

Hier zijn kleine hulpfuncties die vaak gebruikte controles verzamelen. Dit maakt taken zoals invoervalidatie eenvoudiger.

 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}
  • Dit zijn zeer veelzijdige functies die herhaaldelijk kunnen worden gebruikt voor invoerverwerking en vergelijkingen. Implementaties die fouten genereren zijn nuttig voor validatiedoeleinden.

Samenvatting van prestaties en best practices

De volgende punten zijn praktisch bij het gebruik van Number.

  • Gebruik in principe het primitieve number-type en vermijd new Number().
  • Kies afhankelijk van het gebruiksdoel tussen Number() (strikt) of parseInt/parseFloat (gedeeltelijke extractie) voor de conversie van string naar getal.
  • Gebruik Number.isNaN en Number.isFinite voor veilige controles.
  • Gebruik voor drijvendekomma-vergelijkingen Number.EPSILON of maak een speciale vergelijkingsfunctie.
  • Wanneer nauwkeurigheid voor gehele getallen vereist is, gebruik Number.isSafeInteger, en gebruik BigInt als de waarde buiten het bereik valt.
  • Je kunt toFixed of toPrecision gebruiken om af te ronden voor weergave, maar houd er rekening mee dat de geretourneerde waarde een string is.

Samenvatting

Number is het basistype voor alle getallen in JavaScript, waaronder gehele getallen, decimalen en speciale waarden (NaN en Infinity). Het is belangrijk om bewust te zijn van typeconversie en drijvendekomma-fouten, en methoden zoals Number.isNaN en Number.EPSILON correct te gebruiken. Als het bereik van veilige gehele getallen wordt overschreden, gebruik dan BigInt, en gebruik toFixed of toPrecision voor afronding en weergave.

Je kunt het bovenstaande artikel volgen met Visual Studio Code op ons YouTube-kanaal. Bekijk ook het YouTube-kanaal.

YouTube Video