Класс `Number` в JavaScript
В этой статье объясняется класс Number в JavaScript.
Мы подробно рассмотрим особенности Number, распространённые ошибки, полезные API и практические примеры шаг за шагом.
YouTube Video
Класс Number в JavaScript
Number — это основной числовой тип в JavaScript, представленный как 64-битное число с плавающей запятой двойной точности по стандарту IEEE-754.
Основы: представление числа и проверка типа
В JavaScript все числа представлены примитивным типом number.
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)
- Этот код демонстрирует разницу между примитивным типом
numberи объектом-обёрткойNumber. Обычно используются примитивы, а не объекты-обёртки.
Особые значения: NaN, Infinity и константы
Number предоставляет специальные значения (NaN, Infinity) и константы.
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
- Целые числа больше или равные
MAX_SAFE_INTEGERмогут быть представлены неточно. ИспользуйтеBigInt, если требуется точность.EPSILONиспользуется для сравнения чисел с плавающей запятой.
Преобразование в число: Number(), parseInt, parseFloat и оператор +
Существует несколько способов преобразовать строку в число, и каждый ведёт себя по-разному.
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()возвращаетNaN, если вся строка не полностью соответствует числовому формату, тогда какparseIntиparseFloatизвлекают распознаваемую числовую часть с начала строки. Безопаснее всегда явно указывать систему счисления при использованииparseInt.
Обработка и проверка NaN: isNaN и Number.isNaN
NaN (Not-A-Number, не число) примечателен тем, что NaN !== NaN. Между ними есть различия: глобальный isNaN приводит типы и может давать ложные срабатывания, поэтому рекомендуется использовать Number.isNaN.
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
- Используйте
Number.isNaNдля проверки чисел и валидации результатов вычислений, чтобы избежать ненужного приведения типов.
Погрешности чисел с плавающей запятой и сравнения с использованием Number.EPSILON
Из-за стандарта IEEE-754 возможны ошибки, такие как 0.1 + 0.2 !== 0.3. Для строгих сравнений обычно используют разницу и 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
- Если сравнение допускает погрешности, рекомендуется надёжная реализация вроде
nearlyEqual, использующая масштабирование и абсолютные разницы.
Проверка целых чисел и безопасных целых (isInteger, isSafeInteger)
Существуют API для проверки, является ли значение целым числом и находится ли оно в диапазоне безопасных целых.
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
- Когда требуется точность для больших целых чисел, используйте
Number.isSafeIntegerдля проверки, а для чисел, выходящих за пределы диапазона, используйтеBigInt.
Отображение и форматирование: toFixed, toPrecision, toString
Существуют методы для управления отображением чисел. toFixed возвращает строку с заданным количеством знаков после запятой, но следует учитывать нюансы округления.
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возвращает строку, будьте внимательны при преобразовании значения обратно в число для вычислений.
Предостережения при конкатенации строк и использовании оператора +
Оператор + используется как для числового сложения, так и для конкатенации строк, из-за чего возможны неожиданные результаты в зависимости от типов данных.
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)
- При смешивании строк и чисел безопаснее явно использовать
String(),Number()или шаблонные строки, чтобы избежать неявного преобразования типов.
Продвинутые случаи использования: Number.parseInt / Number.parseFloat, valueOf
Number.parseInt и Number.parseFloat — это алиасы глобальных функций. valueOf используется для получения примитивного значения из объекта Number, но на практике требуется редко.
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)
- При использовании
Number.parseIntиNumber.parseFloatбудьте внимательны с указанием системы счисления и обрезкой строки. Объектов-обёрток обычно избегают.
Справка: небольшой утилитный пример — функции проверки чисел
Вот небольшие утилитные функции, которые объединяют часто используемые проверки. Это упрощает задачи, например, валидацию ввода.
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}- Это очень универсальные функции, которые можно многократно использовать для обработки ввода и сравнений. Реализации, выбрасывающие ошибки, полезны для целей валидации.
Резюме по производительности и лучшим практикам
Вот практические советы по использованию Number.
- В целом, используйте примитивный тип
numberи избегайтеnew Number(). - Выбирайте между
Number()(строгое преобразование) илиparseInt/parseFloat(частичное извлечение) для преобразования строки в число в зависимости от задачи. - Используйте
Number.isNaNиNumber.isFiniteдля безопасной проверки. - Для сравнения чисел с плавающей запятой используйте
Number.EPSILONили создайте специализированную функцию сравнения. - Когда требуется точность целых чисел, используйте
Number.isSafeInteger; если диапазон превышен — используйтеBigInt. - Вы можете использовать
toFixedилиtoPrecisionдля округления при отображении, но имейте в виду, что возвращаемое значение — это строка.
Резюме
Number — это базовый тип для всех чисел в JavaScript, включая целые, дробные и специальные значения (NaN и Infinity). Важно учитывать преобразование типов и ошибки с плавающей запятой, а также правильно использовать методы вроде Number.isNaN и Number.EPSILON. Если диапазон безопасных целых превышен, используйте BigInt, а для округления и отображения используйте toFixed или toPrecision.
Вы можете следовать этой статье, используя Visual Studio Code на нашем YouTube-канале. Пожалуйста, также посмотрите наш YouTube-канал.