Back

¿Cuándo podrías necesitar BigInt en JavaScript?

¿Cuándo podrías necesitar BigInt en JavaScript?

JavaScript maneja la mayoría de los números sin problemas, hasta que deja de hacerlo. Si alguna vez has obtenido un ID grande desde una API y notaste que llegó ligeramente incorrecto, o intentaste hacer aritmética precisa con un entero muy grande y obtuviste un resultado sutilmente incorrecto, ya te has encontrado con el problema que BigInt resuelve.

Puntos Clave

  • Los números de JavaScript utilizan el formato de punto flotante de doble precisión IEEE 754, que limita los enteros seguros al rango −(2⁵³ − 1) a 2⁵³ − 1. Más allá de eso, los valores pierden precisión silenciosamente.
  • BigInt es un tipo primitivo (introducido en ES2020) que representa enteros de tamaño arbitrario, pero no puede manejar decimales.
  • Los casos de uso del mundo real incluyen el manejo de IDs externos grandes (por ejemplo, Twitter Snowflake IDs), enteros de 64 bits de WebAssembly y aritmética exacta para contadores grandes o datos de blockchain.
  • BigInt no puede mezclarse con Number en expresiones, no funciona con la API Math y requiere manejo personalizado para la serialización JSON.

El límite que los números de JavaScript no pueden cruzar

Todos los números de JavaScript utilizan el formato de punto flotante de doble precisión IEEE 754. Esto te proporciona un rango de enteros seguros de −(2⁵³ − 1) a 2⁵³ − 1, representado por Number.MIN_SAFE_INTEGER y Number.MAX_SAFE_INTEGER.

Más allá de ese límite, los enteros pierden precisión silenciosamente:

console.log(9007199254740991 + 1)  // 9007199254740992 ✅
console.log(9007199254740991 + 2)  // 9007199254740992 ❌ (incorrecto)

// Este es el problema de precisión en acción:
9007199254740992 === 9007199254740993 // true — son iguales para JavaScript

No se lanza ningún error. El valor simplemente está incorrecto. Ese es el problema del límite de precisión que BigInt fue diseñado para resolver.

Qué es realmente BigInt

BigInt es un tipo primitivo integrado en JavaScript introducido en ES2020 que puede representar enteros de tamaño arbitrario, limitado únicamente por la memoria disponible. Puedes crear uno añadiendo n a un literal entero o usando el constructor BigInt():

const big = 9007199254740993n                 // sintaxis literal
const alsoBig = BigInt("9007199254740993")    // constructor con string

9007199254740992n === 9007199254740993n        // false ✅ — correcto

Una restricción importante: BigInt es solo para enteros. No puede representar decimales o valores fraccionarios. 1.5n lanza un SyntaxError.

Cuándo usar BigInt en JavaScript

La mayoría del código frontend nunca necesita BigInt. Pero algunos escenarios del mundo real genuinamente lo requieren.

IDs grandes de sistemas externos. El sistema de Snowflake ID de Twitter y esquemas similares de IDs distribuidos producen enteros de 64 bits que exceden Number.MAX_SAFE_INTEGER. Cuando una API REST devuelve uno de estos como un número JSON, JavaScript lo corromperá silenciosamente. Parsearlo como string y convertirlo a BigInt preserva el valor exactamente.

// Un ID de 64 bits recibido como string desde una API
const userId = BigInt("922337203685477580")

Enteros de 64 bits desde WebAssembly. El tipo i64 de WebAssembly se mapea directamente a BigInt en JavaScript. Si tu módulo Wasm devuelve o acepta enteros de 64 bits, necesitarás BigInt para manejarlos correctamente.

Aritmética exacta de enteros donde la precisión nunca debe fallar. Ciertos valores de transacciones blockchain, contadores grandes o aritmética de marcas de tiempo de alta precisión (por ejemplo, nanosegundos desde epoch) pueden exceder el rango de enteros seguros. BigInt mantiene cada dígito exacto.

Restricciones importantes a conocer

Antes de recurrir a BigInt, comprende sus limitaciones:

No puedes mezclar BigInt y Number en aritmética. Hacerlo lanza un TypeError. Se requiere conversión explícita:

const big = 10n
const num = 5

big + num            // ❌ TypeError
big + BigInt(num)    // ✅ 15n
Number(big) + num    // ✅ 15 (pero pierde precisión de BigInt para valores grandes)

La API Math no funciona con BigInt. Math.max(), Math.sqrt() y todos los demás métodos de Math lanzarán un error si se les pasa un BigInt. Si necesitas estas operaciones, tendrás que convertir y aceptar el compromiso de precisión.

La serialización JSON falla por defecto. JSON.stringify() lanza un TypeError en valores BigInt. Necesitas un replacer personalizado o un método toJSON() para manejar la serialización:

BigInt.prototype.toJSON = function () {
  return this.toString()
}

JSON.stringify({ id: 922337203685477580n }) // '{"id":"922337203685477580"}'

Ten en cuenta que esto convierte el valor a un string en la salida JSON, que el sistema receptor necesita manejar en consecuencia. Además, modificar un prototipo integrado como BigInt.prototype generalmente se desaconseja en código de producción. Una función replacer personalizada pasada a JSON.stringify() es una alternativa más segura:

const data = { id: 922337203685477580n }

JSON.stringify(data, (key, value) =>
  typeof value === "bigint" ? value.toString() : value
) // '{"id":"922337203685477580"}'

Conclusión

BigInt vs Number en JavaScript realmente no es una competencia: sirven propósitos diferentes. Usa Number para todo lo que maneja bien, que es la mayoría de las cosas. Recurre a BigInt específicamente cuando trabajes con enteros que pueden exceder 2⁵³ − 1 y donde la exactitud no es negociable. Esa es una categoría estrecha pero importante, y BigInt la maneja exactamente bien.

Preguntas Frecuentes

BigInt es compatible con todos los navegadores modernos, incluyendo Chrome, Firefox, Safari y Edge. Sin embargo, Internet Explorer no lo soporta. Si necesitas dar soporte a IE, deberás mantener los valores como strings o usar una biblioteca de números grandes en lugar de depender del BigInt nativo.

Sí. Puedes comparar valores BigInt con otros BigInts usando operadores de comparación estándar como menor que, mayor que e igualdad estricta. También puedes usar igualdad débil para comparar un BigInt con un Number, así que 10n == 10 devuelve true, pero 10n === 10 devuelve false porque son tipos diferentes.

Sí. Las operaciones BigInt son generalmente más lentas que las operaciones Number porque usan aritmética de precisión arbitraria en lugar de instrucciones de hardware de tamaño fijo. Para la mayoría de las aplicaciones la diferencia es insignificante, pero en bucles críticos de rendimiento o rutas calientes, deberías hacer benchmarks y preferir Number cuando los valores se mantengan dentro del rango de enteros seguros.

Usa el constructor Number, como Number(100n), que devuelve 100. Sin embargo, ten cuidado con valores grandes. Si el BigInt excede Number.MAX_SAFE_INTEGER, la conversión perderá precisión silenciosamente. Siempre verifica si el valor cabe dentro del rango seguro antes de convertir.

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.

OpenReplay