Índice
- El problema
- La solución
- Conversión de tipo implícita
- El constructor BigInt
- Funciones de biblioteca
- Soporte y transpilación del navegador
- Conclusión
En JavaScript, el Number
tipo no puede representar de forma segura valores enteros mayores que 2 53 . Esta limitación ha obligado a los desarrolladores a utilizar soluciones alternativas ineficientes y bibliotecas de terceros. BigInt
es un nuevo tipo de datos destinado a solucionar este problema.
El BigInt
tipo de datos tiene como objetivo permitir a los programadores de JavaScript representar valores enteros mayores que el rango admitido por el Number
tipo de datos. La capacidad de representar números enteros con precisión arbitraria es particularmente importante cuando se realizan operaciones matemáticas con números enteros grandes. Con BigInt
, el desbordamiento de enteros ya no será un problema.
Además, puede trabajar de forma segura con marcas de tiempo de alta resolución, ID de números enteros grandes y más sin tener que utilizar una solución alternativa. BigInt
Actualmente es una propuesta de etapa 3. Una vez agregado a la especificación, se convertirá en el segundo tipo de datos numéricos en JavaScript, lo que elevará a ocho el número total de tipos de datos admitidos:
- Booleano
- Nulo
- Indefinido
- Número
- Empezando
- Cadena
- Símbolo
- Objeto
En este artículo, analizaremos detenidamente BigInt
y veremos cómo puede ayudar a superar las limitaciones del Number
tipo en JavaScript.
El problema
La falta de un tipo entero explícito en JavaScript suele resultar desconcertante para los programadores que utilizan otros lenguajes. Muchos lenguajes de programación admiten múltiples tipos numéricos, como flotante, doble, entero y bignum, pero ese no es el caso de JavaScript. En JavaScript, todos los números se representan en formato de punto flotante de 64 bits de doble precisión según lo definido por el estándar IEEE 754-2008 .
Según este estándar, los números enteros muy grandes que no se pueden representar exactamente se redondean automáticamente. Para ser precisos, el Number
tipo en JavaScript solo puede representar de forma segura números enteros entre -9007199254740991 (-(2 53 -1)) y 9007199254740991 (2 53 -1). Cualquier valor entero que quede fuera de este rango puede perder precisión.
Esto se puede examinar fácilmente ejecutando el siguiente código:
console.log(9999999999999999); // → 10000000000000000
Este número entero es mayor que el número más grande que JavaScript puede representar de manera confiable con la Number
primitiva. Por tanto, es redondeado. Un redondeo inesperado puede comprometer la confiabilidad y seguridad de un programa. Aquí hay otro ejemplo:
// notice the last digits9007199254740992 === 9007199254740993; // → true
JavaScript proporciona la Number.MAX_SAFE_INTEGER
constante que le permite obtener rápidamente el número entero seguro máximo en JavaScript. De manera similar, puedes obtener el entero mínimo seguro usando la Number.MIN_SAFE_INTEGER
constante:
const minInt = Number.MIN_SAFE_INTEGER;console.log(minInt); // → -9007199254740991console.log(minInt - 5); // → -9007199254740996// notice how this outputs the same value as aboveconsole.log(minInt - 4); // → -9007199254740996
La solución
Como solución alternativa a estas limitaciones, algunos desarrolladores de JavaScript representan números enteros grandes utilizando el String
tipo. La API de Twitter , por ejemplo, agrega una versión de cadena de ID a los objetos cuando responde con JSON. Además, se han desarrollado varias bibliotecas como bignumber.js para facilitar el trabajo con números enteros grandes.
Con BigInt
, las aplicaciones ya no necesitan una solución alternativa o una biblioteca para representar de forma segura números enteros más allá de Number.MAX_SAFE_INTEGER
y Number.Min_SAFE_INTEGER
. Las operaciones aritméticas con números enteros grandes ahora se pueden realizar en JavaScript estándar sin riesgo de pérdida de precisión. El beneficio adicional de utilizar un tipo de datos nativo en lugar de una biblioteca de terceros es un mejor rendimiento en tiempo de ejecución.
Para crear un BigInt
, simplemente agréguelo n
al final de un número entero. Comparar:
console.log(9007199254740995n); // → 9007199254740995nconsole.log(9007199254740995); // → 9007199254740996
Alternativamente, puedes llamar al BigInt()
constructor:
BigInt("9007199254740995"); // → 9007199254740995n
BigInt
Los literales también se pueden escribir en notación binaria, octal o hexadecimal:
// binaryconsole.log(0b100000000000000000000000000000000000000000000000000011n);// → 9007199254740995n// hexconsole.log(0x20000000000003n);// → 9007199254740995n// octalconsole.log(0o400000000000000003n);// → 9007199254740995n// note that legacy octal syntax is not supportedconsole.log(0400000000000000003n);// → SyntaxError
Tenga en cuenta que no puede utilizar el operador de igualdad estricta para comparar a BigInt
con un número normal porque no son del mismo tipo:
console.log(10n === 10); // → falseconsole.log(typeof 10n); // → bigintconsole.log(typeof 10); // → number
En su lugar, puedes usar el operador de igualdad, que realiza una conversión de tipo implícita antes de comparar sus operandos:
console.log(10n == 10); // → true
Todos los operadores aritméticos se pueden utilizar en BigInt
s excepto el +
operador unario más ( ):
10n + 20n; // → 30n10n - 20n; // → -10n+10n; // → TypeError: Cannot convert a BigInt value to a number-10n; // → -10n10n * 20n; // → 200n20n / 10n; // → 2n23n % 10n; // → 3n10n ** 3n; // → 1000nlet x = 10n;++x; // → 11n--x; // → 10n
La razón por la que +
no se admite el operador unario más ( ) es que algunos programas pueden depender del invariante que +
siempre produce un Number
, o genera una excepción. Cambiar el comportamiento +
también rompería el código asm.js. Significado de refranes
Naturalmente, cuando se utilizan con BigInt
operandos, se espera que los operadores aritméticos devuelvan un BigInt
valor. Por lo tanto, el resultado del /
operador división ( ) se trunca automáticamente. Por ejemplo:
25 / 10; // → 2.525n / 10n; // → 2n
Conversión de tipo implícita
Debido a que la conversión de tipos implícita podría perder información, no se permiten operaciones mixtas entre BigInt
sys . Number
Al mezclar números enteros grandes y números de punto flotante, es posible que el valor resultante no se pueda representar con precisión mediante BigInt
o Number
. Considere el siguiente ejemplo:
(9007199254740992n + 1n) + 0.5
El resultado de esta expresión está fuera del dominio de ambos BigInt
y Number
. A Number
con una parte fraccionaria no se puede convertir con precisión en un BigInt
. Y un BigInt
valor mayor que 2 53 no se puede convertir con precisión a Number
.
Como resultado de esta restricción, no es posible realizar operaciones aritméticas con una combinación de operandos Number
y . BigInt
Tampoco puede pasar BigInt
a las API web ni a las funciones JavaScript integradas que esperan un archivo Number
. Intentar hacerlo provocará TypeError
:
10 + 10n; // → TypeErrorMath.max(2n, 4n, 6n); // → TypeError
Tenga en cuenta que los operadores relacionales no siguen esta regla, como se muestra en este ejemplo:
10n 5; // → true
Si desea realizar cálculos aritméticos con BigInt
y Number
, primero debe determinar el dominio en el que se debe realizar la operación. Para hacer eso, simplemente convierta cualquiera de los operandos llamando Number()
a o BigInt()
:
BigInt(10) + 10n; // → 20n// or10 + Number(10n); // → 20
Cuando se encuentra en un Boolean
contexto, BigInt
se trata de manera similar a Number
. En otras palabras, a BigInt
se considera un valor verdadero siempre que no sea 0n
:
if (5n) { // this code block will be executed}if (0n) { // but this code block won't}
No se produce ninguna conversión de tipos implícita entre BigInt
los Number
tipos y al ordenar una matriz:
const arr = [3n, 4, 2, 1n, 0, -1n];arr.sort(); // → [-1n, 0, 1n, 2, 3n, 4]
Los operadores bit a bit como |
, ,
,
y
^
operan en BigInt
s de manera similar a Number
s. Los números negativos se interpretan como complemento a dos de longitud infinita. No se permiten operandos mixtos. Aquí hay unos ejemplos:
90 | 115; // → 12390n | 115n; // → 123n90n | 115; // → TypeError
El constructor BigInt
Al igual que con otros tipos primitivos, se BigInt
puede crear usando una función constructora. El argumento pasado a BigInt()
se convierte automáticamente en BigInt
, si es posible:
BigInt("10"); // → 10nBigInt(10); // → 10nBigInt(true); // → 1n
Los tipos de datos y valores que no se pueden convertir generan una excepción:
BigInt(10.2); // → RangeErrorBigInt(null); // → TypeErrorBigInt("abc"); // → SyntaxError
Puede realizar operaciones aritméticas directamente en un BigInt
objeto creado utilizando un constructor:
BigInt(10) * 10n; // → 100n
Cuando se usan como operandos del operador de igualdad estricta, BigInt
los mensajes creados usando un constructor se tratan de manera similar a los normales:
BigInt(true) === 1n; // → true
Funciones de biblioteca
JavaScript proporciona dos funciones de biblioteca para representar BigInt
valores como enteros con o sin signo:
BigInt.asUintN(width, BigInt)
: envuelve un anchoBigInt
entre 0 y 2 -1BigInt.asIntN(width, BigInt)
: envuelve unBigInt
entre -2 ancho-1 y 2 ancho-1 -1
Estas funciones son particularmente útiles cuando se realizan operaciones aritméticas de 64 bits. De esta manera podrá mantenerse dentro del rango previsto.
Soporte y transpilación del navegador
Al momento de escribir este artículo, Chrome +67 y Opera +54 son totalmente compatibles con el BigInt
tipo de datos. Desafortunadamente, Edge y Safari aún no lo han implementado. Firefox no es compatible de forma BigInt
predeterminada, pero se puede habilitar configurando javascript.options.bigint
en . Una lista actualizada de navegadores compatibles está disponible en ¿Puedo usar... ?true
about:config
Desafortunadamente, la transpilación BigInt
es un proceso extremadamente complicado , que conlleva una considerable penalización en el rendimiento en tiempo de ejecución. También es imposible realizar un polyfill directamente BigInt
porque la propuesta cambia el comportamiento de varios operadores existentes. Por ahora, una mejor alternativa es utilizar la biblioteca JSBI , que es una implementación puramente de JavaScript de la BigInt
propuesta.
Esta biblioteca proporciona una API que se comporta exactamente igual que la nativa BigInt
. Así es como puedes usar JSBI:
import JSBI from './jsbi.mjs';const b1 = JSBI.BigInt(Number.MAX_SAFE_INTEGER);const b2 = JSBI.BigInt('10');const result = JSBI.add(b1, b2);console.log(String(result)); // → '9007199254741001'
Una ventaja de utilizar JSBI es que una vez que mejore la compatibilidad del navegador, no será necesario volver a escribir el código. En su lugar, puede compilar automáticamente su código JSBI en BigInt
código nativo utilizando un complemento de Babel . Además, el rendimiento de JSBI está a la par de BigInt
las implementaciones nativas. Puede esperar una mayor compatibilidad con el navegador pronto BigInt
.
Conclusión
BigInt
es un nuevo tipo de datos destinado a usarse cuando los valores enteros son mayores que el rango admitido por el Number
tipo de datos. Este tipo de datos nos permite realizar operaciones aritméticas de forma segura en números enteros grandes, representar marcas de tiempo de alta resolución, usar ID de números enteros grandes y más sin la necesidad de usar una biblioteca.
Es importante tener en cuenta que no se pueden realizar operaciones aritméticas con una combinación de operandos Number
y . BigInt
Deberá determinar el dominio en el que se debe realizar la operación convirtiendo explícitamente cualquiera de los operandos. Además, por motivos de compatibilidad, no está permitido utilizar el +
operador unario más ( ) en un archivo BigInt
.
¿Qué opinas? ¿Te resulta BigInt
útil? ¡Háganos saber en los comentarios!
(dm, yk, il)Explora más en
- javascript
- Técnicas
Tal vez te puede interesar:
- ¿Deberían abrirse los enlaces en ventanas nuevas?
- 24 excelentes tutoriales de AJAX
- 70 técnicas nuevas y útiles de AJAX y JavaScript
- Más de 45 excelentes recursos y repositorios de fragmentos de código
La guía esencial para el tipo de datos más nuevo de JavaScript: BigInt
El problemaLa soluciónConversión de tipo implícitaEl constructor BigIntFunciones de bibliotecaSoporte y transpilación del navegadorConclusiónPatrones de d
programar
es
https://aprendeprogramando.es/static/images/programar-la-guia-esencial-para-el-tipo-de-datos-mas-nuevo-de-javascript-bigint-992-0.jpg
2024-12-03
Si crees que alguno de los contenidos (texto, imagenes o multimedia) en esta página infringe tus derechos relativos a propiedad intelectual, marcas registradas o cualquier otro de tus derechos, por favor ponte en contacto con nosotros en el mail [email protected] y retiraremos este contenido inmediatamente