The `Number` Class in JavaScript
This article explains the Number class in JavaScript.
We will carefully explain the characteristics of Number, common pitfalls, useful APIs, and practical examples step by step.
YouTube Video
The Number Class in JavaScript
Number is the fundamental numeric type in JavaScript and is represented as an IEEE-754 double-precision floating point (64-bit).
Basics: Number Representation and Type Checking
In JavaScript, all numbers are represented as the primitive 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)
- This code demonstrates the difference between a primitive
numberand theNumberwrapper object. Normally, primitives are used instead of wrappers.
Special Values: NaN, Infinity, and Constants
Number provides special values (NaN, Infinity) and constants.
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
- Integers greater than or equal to
MAX_SAFE_INTEGERmay not be represented accurately. Consider usingBigIntif accuracy is required.EPSILONis used for floating-point comparisons.
Number Conversion: Number(), parseInt, parseFloat, and + Operator
There are several ways to convert a string to a number, each with different behaviors.
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()returnsNaNunless the whole string is strictly in numeric format, whereasparseIntandparseFloatparse the readable numeric part from the beginning of the string. It is safer to always explicitly specify the radix when usingparseInt.
Handling and Checking NaN: isNaN and Number.isNaN
NaN (Not-A-Number) is special in that NaN !== NaN. There are differences in how they check; the global isNaN performs type conversion and may result in false positives, so Number.isNaN is recommended.
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
- Use
Number.isNaNfor checking numbers and validating calculation results to avoid unnecessary type conversion.
Floating-Point Errors and Comparisons Using Number.EPSILON
Due to IEEE-754, errors such as 0.1 + 0.2 !== 0.3 occur. For strict comparisons, it is common to use the difference and 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
- When allowing for errors in comparison, a robust implementation like
nearlyEqualthat also performs scaling as well as using absolute differences is recommended.
Checking Integers and Safe Integers (isInteger, isSafeInteger)
There are APIs to check whether a value is an integer and whether it is within the safe integer range.
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
- When accuracy of large integers is necessary, use
Number.isSafeIntegerto check, and consider usingBigIntfor numbers exceeding that range.
Display and Formatting: toFixed, toPrecision, toString
There are methods available to control the display of numbers. toFixed returns a string with a specified number of decimal places, but care should be taken with rounding.
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)
toFixedreturns a string, so be aware of values after converting them to numbers for calculations.
Cautions Regarding String Concatenation and + Operator
The + operator is used for both numeric addition and string concatenation, so unintended results may occur depending on the data types involved.
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)
- When strings and numbers are mixed, it is safer to explicitly use
String(),Number(), or template literals to avoid implicit type conversion.
Advanced Use Cases: Number.parseInt / Number.parseFloat, valueOf
Number.parseInt and Number.parseFloat are aliases of the global functions. valueOf is used to retrieve the primitive value from a Number object, but it is rarely needed in practice.
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)
- When using
Number.parseIntandNumber.parseFloat, be careful with the radix and trimming the input. Wrapper objects are usually avoided.
Reference: Small Utility Example - Number Validation Functions
Here are small utility functions that collect commonly used checks. This makes tasks such as input validation easier.
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}- These are highly versatile functions that can be used repeatedly for input processing and comparisons. Implementations that throw errors are useful for validation purposes.
Summary of Performance and Best Practices
The following are practical points when using Number.
- Basically, use the primitive
numbertype and avoidnew Number(). - Choose between
Number()(strict) orparseInt/parseFloat(partial extraction) for string-to-number conversion depending on your use case. - Use
Number.isNaNandNumber.isFinitefor safe checking. - For floating-point comparisons, use
Number.EPSILONor create a dedicated comparison function. - When integer accuracy is required, use
Number.isSafeInteger, and if it exceeds the range, useBigInt. - You can use
toFixedortoPrecisionfor rounding for display, but note that the return value is a string.
Summary
Number is the basic type for all numbers in JavaScript, including integers, decimals, and special values (NaN and Infinity). It is important to be aware of type conversion and floating-point errors, and to use methods such as Number.isNaN and Number.EPSILON correctly. If the safe integer range is exceeded, use BigInt, and use toFixed or toPrecision for rounding and display.
You can follow along with the above article using Visual Studio Code on our YouTube channel. Please also check out the YouTube channel.