Когда может понадобиться BigInt в JavaScript?
JavaScript прекрасно справляется с большинством чисел — пока не перестаёт. Если вы когда-либо получали большой ID из API и замечали, что он возвращался слегка искажённым, или пытались выполнить точные арифметические операции с очень большим целым числом и получали незаметно неверный результат, вы уже сталкивались с проблемой, которую решает BigInt.
Ключевые моменты
- Числа в JavaScript используют формат IEEE 754 с двойной точностью, что ограничивает безопасные целые числа диапазоном −(2⁵³ − 1) до 2⁵³ − 1. За его пределами значения теряют точность незаметно.
BigInt— это примитивный тип (введён в ES2020), который представляет целые числа произвольного размера, но не может работать с десятичными дробями.- Реальные сценарии использования включают обработку больших внешних ID (например, Twitter Snowflake ID), 64-битных целых чисел WebAssembly и точную арифметику для больших счётчиков или данных блокчейна.
- BigInt нельзя смешивать с Number в выражениях, он не работает с API
Mathи требует специальной обработки для JSON-сериализации.
Предел, который числа JavaScript не могут преодолеть
Все числа в JavaScript используют формат IEEE 754 с двойной точностью с плавающей запятой. Это даёт вам безопасный диапазон целых чисел −(2⁵³ − 1) до 2⁵³ − 1, представленный константами Number.MIN_SAFE_INTEGER и Number.MAX_SAFE_INTEGER.
За пределами этой границы целые числа теряют точность незаметно:
console.log(9007199254740991 + 1) // 9007199254740992 ✅
console.log(9007199254740991 + 2) // 9007199254740992 ❌ (неверно)
// Это проблема точности в действии:
9007199254740992 === 9007199254740993 // true — для JavaScript они одинаковы
Ошибка не выбрасывается. Значение просто неверное. Это проблема ограничения точности, для решения которой был разработан BigInt.
Что такое BigInt на самом деле
BigInt — это встроенный примитивный тип JavaScript, введённый в ES2020, который может представлять целые числа произвольного размера, ограниченные только доступной памятью. Вы создаёте его, добавляя n к целочисленному литералу или используя конструктор BigInt():
const big = 9007199254740993n // синтаксис литерала
const alsoBig = BigInt("9007199254740993") // конструктор со строкой
9007199254740992n === 9007199254740993n // false ✅ — правильно
Одно важное ограничение: BigInt работает только с целыми числами. Он не может представлять десятичные или дробные значения. 1.5n вызывает SyntaxError.
Когда использовать BigInt в JavaScript
Большинству фронтенд-кода BigInt никогда не понадобится. Но есть несколько реальных сценариев, которые действительно требуют его использования.
Большие ID из внешних систем. Система Snowflake ID от Twitter и аналогичные схемы распределённых ID генерируют 64-битные целые числа, которые превышают Number.MAX_SAFE_INTEGER. Когда REST API возвращает такой ID как JSON-число, JavaScript незаметно исказит его. Парсинг его как строки и преобразование в BigInt сохраняет значение точно.
// 64-битный ID, полученный как строка из API
const userId = BigInt("922337203685477580")
64-битные целые числа из WebAssembly. Тип i64 в WebAssembly напрямую соответствует BigInt в JavaScript. Если ваш Wasm-модуль возвращает или принимает 64-битные целые числа, вам понадобится BigInt для корректной работы с ними.
Точная целочисленная арифметика, где точность никогда не должна теряться. Определённые значения транзакций блокчейна, большие счётчики или арифметика временных меток высокой точности (например, наносекунды с начала эпохи) могут превышать диапазон безопасных целых чисел. BigInt сохраняет каждую цифру точно.
Discover how at OpenReplay.com.
Важные ограничения, которые нужно знать
Прежде чем использовать BigInt, поймите его ограничения:
Нельзя смешивать BigInt и Number в арифметических операциях. Это вызывает TypeError. Требуется явное преобразование:
const big = 10n
const num = 5
big + num // ❌ TypeError
big + BigInt(num) // ✅ 15n
Number(big) + num // ✅ 15 (но теряет точность BigInt для больших значений)
API Math не работает с BigInt. Math.max(), Math.sqrt() и любой другой метод Math выбросят ошибку при передаче BigInt. Если вам нужны эти операции, придётся преобразовывать — и принять компромисс в точности.
JSON-сериализация по умолчанию не работает. JSON.stringify() выбрасывает TypeError для значений BigInt. Вам нужна пользовательская функция replacer или метод toJSON() для обработки сериализации:
BigInt.prototype.toJSON = function () {
return this.toString()
}
JSON.stringify({ id: 922337203685477580n }) // '{"id":"922337203685477580"}'
Обратите внимание, что это преобразует значение в строку в JSON-выводе, что принимающая система должна соответствующим образом обработать. Также изменение встроенного прототипа вроде BigInt.prototype обычно не рекомендуется в production-коде. Более безопасная альтернатива — пользовательская функция replacer, передаваемая в JSON.stringify():
const data = { id: 922337203685477580n }
JSON.stringify(data, (key, value) =>
typeof value === "bigint" ? value.toString() : value
) // '{"id":"922337203685477580"}'
Итог
BigInt против Number в JavaScript — это не совсем конкуренция, они служат разным целям. Используйте Number для всего, с чем он хорошо справляется, а это большинство вещей. Обращайтесь к BigInt конкретно тогда, когда вы работаете с целыми числами, которые могут превышать 2⁵³ − 1, и где корректность не подлежит обсуждению. Это узкая, но важная категория, и BigInt справляется с ней абсолютно правильно.
Часто задаваемые вопросы
BigInt поддерживается во всех современных браузерах, включая Chrome, Firefox, Safari и Edge. Однако Internet Explorer его не поддерживает. Если вам нужна поддержка IE, вам придётся хранить значения как строки или использовать библиотеку для работы с большими числами вместо нативного BigInt.
Да. Вы можете сравнивать значения BigInt с другими BigInt, используя стандартные операторы сравнения, такие как меньше, больше и строгое равенство. Вы также можете использовать нестрогое равенство для сравнения BigInt с Number, поэтому 10n == 10 возвращает true, но 10n === 10 возвращает false, потому что это разные типы.
Да. Операции с BigInt обычно медленнее операций с Number, потому что они используют арифметику произвольной точности, а не инструкции фиксированного размера на уровне процессора. Для большинства приложений разница незначительна, но в критичных по производительности циклах или горячих путях следует провести бенчмарки и предпочесть Number, когда значения остаются в диапазоне безопасных целых чисел.
Используйте конструктор Number, например Number(100n), который вернёт 100. Однако будьте осторожны с большими значениями. Если BigInt превышает Number.MAX_SAFE_INTEGER, преобразование незаметно потеряет точность. Всегда проверяйте, помещается ли значение в безопасный диапазон перед преобразованием.
Complete picture for complete understanding
Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.
Check our GitHub repo and join the thousands of developers in our community.