JavaScript Numbers
JavaScript has only one type of number. Unlike many programming languages that have separate integer and floating-point types, JavaScript stores all numbers as double-precision 64-bit floating-point values following the IEEE 754 standard.
Number Basics
JavaScript numbers are always stored as double-precision floating-point numbers, regardless of whether they're written as integers or decimals. This means 5 and 5.0 are the same value internally. The IEEE 754 standard specifies how these numbers are represented in memory, providing a range from approximately 5e-324 to 1.8e+308.
Numbers can be written with or without decimal points. Integer literals like 42, 1000, or -7 work perfectly. Decimal (floating-point) literals use a decimal point: 3.14, 0.5, -2.75. Both forms are stored identically as floating-point values, so there's no performance difference or type distinction between writing 10 versus 10.0.
Extra large or extra small numbers can be written using scientific (exponential) notation with the letter 'e'. For example, 1.23e5 means 1.23 × 10^5 = 123000, and 1.23e-5 means 1.23 × 10^-5 = 0.0000123. Scientific notation is useful for very large numbers (like astronomical distances) or very small numbers (like atomic measurements) to avoid writing many zeros.
JavaScript numbers are accurate up to approximately 15 digits. Beyond this, precision can be lost due to floating-point representation limitations. For example, 999999999999999 (15 nines) is accurate, but 9999999999999999 (16 nines) gets rounded. This is important for financial calculations or applications requiring high precision—consider using specialized libraries or BigInt for integers.
Integer precision is guaranteed up to Number.MAX_SAFE_INTEGER (2^53 - 1 = 9007199254740991) and Number.MIN_SAFE_INTEGER (-9007199254740991). Beyond these values, integers may lose precision. You can check if an integer is in the safe range with Number.isSafeInteger(). For larger integers, use the BigInt type introduced in ES2020.
// Integer
let x = 123;
// Decimal
let y = 123.456;
// Scientific notation
let z = 123e5; // 12300000
let w = 123e-5; // 0.00123
// Precision
let a = 0.1 + 0.2;
console.log(a); // 0.30000000000000004
// Large numbers
let big = 999999999999999; // 15 digits
let bigger = 9999999999999999; // 16 digits (precision lost)
Special Number Values
Infinity is a special numeric value representing mathematical infinity. It results from operations like dividing a positive number by zero (1 / 0), or from numbers too large to represent (exceeding Number.MAX_VALUE). Infinity is greater than any other number. You can use it in comparisons and calculations, where Infinity + 1 still equals Infinity. It's a number: typeof Infinity returns "number".
-Infinity (negative infinity) represents negative mathematical infinity. It results from dividing a negative number by zero (-1 / 0) or from negative numbers too large in magnitude to represent. -Infinity is less than any other number. Like Infinity, it participates in arithmetic: -Infinity - 1 still equals -Infinity. Both Infinity values are useful for representing unbounded ranges or impossible calculations.
NaN stands for "Not a Number" and represents a computational error or undefined mathematical operation. Despite its name, typeof NaN returns "number". NaN results from invalid operations like "hello" / 2, Math.sqrt(-1), or 0 / 0. NaN has a unique property: it's not equal to anything, including itself (NaN === NaN is false). This makes NaN checking tricky—you must use isNaN() or Number.isNaN().
The isNaN() function checks if a value is NaN. However, isNaN() coerces its argument to a number first, which can produce unexpected results. For example, isNaN("hello") returns true because "hello" converts to NaN. For more reliable checking without coercion, use Number.isNaN(), which only returns true for actual NaN values without attempting type conversion.
The isFinite() function checks if a value is a finite number (not Infinity, -Infinity, or NaN). Like isNaN(), it coerces its argument to a number first. isFinite(123) returns true, while isFinite(Infinity), isFinite(NaN), and isFinite("hello") return false. For stricter checking without coercion, use Number.isFinite(), which only returns true for actual finite numbers.
// Infinity
let inf = 1 / 0;
console.log(inf); // Infinity
let negInf = -1 / 0;
console.log(negInf); // -Infinity
// NaN
let notNum = "Hello" / 2;
console.log(notNum); // NaN
// isNaN
console.log(isNaN(notNum)); // true
console.log(isNaN(123)); // false
// isFinite
console.log(isFinite(123)); // true
console.log(isFinite(Infinity)); // false