Le guide essentiel de la nouvelle version de JavaScript: BigInt
Le type de données BigInt
vise à permettre aux programmeurs JavaScript de représenter des valeurs entières supérieures à la plage prise en charge par le type de données Number
. La possibilité de représenter des entiers avec une précision arbitraire est particulièrement importante lors de l'exécution d'opérations mathématiques sur de grands entiers. Avec BigInt
le dépassement d'entier ne constitue plus un problème.
De plus, vous pouvez travailler en toute sécurité avec des horodatages à haute résolution, des identificateurs d'entiers de grande taille, etc. sans avoir recours à une solution de contournement. BigInt
est actuellement une proposition de stade 3. Une fois ajouté à la spécification, il deviendra le deuxième type de données numérique en JavaScript, ce qui portera le nombre total de types de données pris en charge à huit:
- Boolean
- Null
- Undefined
- Number
- BigInt
- String
- Symbole
- Object
Dans cet article, nous allons examiner de près BigInt
et voir comment il peut aider à surmonter les limitations du Number
. ] tapez JavaScript.
Le problème
L'absence d'un type entier explicite en JavaScript est souvent déconcertante pour les programmeurs venant d'autres langages. De nombreux langages de programmation prennent en charge plusieurs types numériques tels que float, double, integer et bignum, mais ce n'est pas le cas avec JavaScript. En JavaScript, tous les nombres sont représentés au format à virgule flottante double précision à 64 bits tel que défini par la norme IEEE 754-2008 .
Selon cette norme, très grands entiers qui ne peuvent pas être exactement représentés sont automatiquement arrondis. Pour être précis, le type Number
en JavaScript ne peut représenter en toute sécurité que des entiers compris entre -9007199254740991 (- (2 53 -1)) et 9007199254740991 (2 53 1). Toute valeur entière qui se situe en dehors de cette plage peut perdre en précision.
Ceci peut être facilement examiné en exécutant le code suivant:
console.log (9999999999999999); // → 10000000000000000
Cet entier est supérieur au plus grand nombre que JavaScript peut représenter de manière fiable avec la primitive Number
. Par conséquent, il est arrondi. Un arrondi inattendu peut compromettre la fiabilité et la sécurité d’un programme. Voici un autre exemple:
// remarquez les derniers chiffres
9007199254740992 === 9007199254740993; // → true
JavaScript fournit la constante Number.MAX_SAFE_INTEGER
qui vous permet d'obtenir rapidement le nombre entier sécurisé maximal en JavaScript. De même, vous pouvez obtenir le nombre entier sécurisé minimal à l'aide de la constante Number.MIN_SAFE_INTEGER
:
const minInt = Number.MIN_SAFE_INTEGER;
console.log (minInt); // → -9007199254740991
console.log (minInt - 5); // → -9007199254740996
// remarque comment cela produit la même valeur que ci-dessus
console.log (minInt - 4); // → -9007199254740996
La solution
Pour contourner ce problème, certains développeurs JavaScript représentent de grands entiers utilisant le type String
. L'API Twitter par exemple, ajoute une version sous forme de chaîne d'ID à des objets lors d'une réponse avec JSON. En outre, un certain nombre de bibliothèques telles que bignumber.js ont été développées pour faciliter l'utilisation des grands entiers.
Avec BigInt
les applications n'ont plus besoin de solution de contournement ni de bibliothèque pour se protéger. représente des nombres entiers au-delà de Number.MAX_SAFE_INTEGER
et Number.Min_SAFE_INTEGER
. Les opérations arithmétiques sur des entiers de grande taille peuvent désormais être effectuées en JavaScript standard sans risquer de perte de précision. L'avantage supplémentaire d'utiliser un type de données natif sur une bibliothèque tierce est une meilleure performance au moment de l'exécution.
Pour créer un BigInt
ajoutez simplement n
à la fin d'un entier. Comparez:
console.log (9007199254740995n); // → 9007199254740995n
console.log (9007199254740995); // → 9007199254740996
Vous pouvez également appeler le constructeur BigInt ()
:
BigInt ("9007199254740995"); // → 9007199254740995n
Les littéraux BigInt
peuvent également être écrits en notation binaire, octale ou hexadécimale:
// binaire
console.log (0b1000000000000000000000000000000000000000000000000000000011n);
// → 9007199254740995n
// hex
console.log (0x20000000000003n);
// → 9007199254740995n
// octal
console.log (0o400000000000000003n);
// → 9007199254740995n
// remarque que la syntaxe octale héritée n'est pas prise en charge
console.log (0400000000000000003n);
// → SyntaxError
N'oubliez pas que vous ne pouvez pas utiliser l'opérateur d'égalité stricte pour comparer un BigInt
à un nombre régulier car ils ne sont pas du même type:
console.log (10n === dix); // → faux
console.log (type de 10n); // → bigint
console.log (type de 10); // → nombre
Vous pouvez utiliser l'opérateur d'égalité, qui effectue une conversion de type implicite avant de compiler ses opérandes:
console.log (10n == 10); // → true
Tous les opérateurs arithmétiques peuvent être utilisés sur les BigInt
sauf les opérateurs unaires plus ( +
):
10n + 20n; // → 30n
10n - 20n; // → -10n
+ 10n; // → TypeError: Impossible de convertir une valeur BigInt en nombre
-10n; // → -10n
10n * 20n; // → 200n
20n / 10n; // → 2n
23n% 10n; // → 3n
10n ** 3n; // → 1000n
const x = 10n;
++ x; // → 11n
--X; // → 9n
La raison pour laquelle l'opérateur unaire plus ( +
) n'est pas pris en charge est que certains programmes peuvent s'appuyer sur l'invariant selon lequel +
produit toujours un numéro
ou lève une exception. Changer le comportement de +
aurait également pour effet de casser le code.
Naturellement, lorsqu'il est utilisé avec les opérandes BigInt
les opérateurs arithmétiques sont supposés renvoyer un BigInt
. valeur. Par conséquent, le résultat de l'opérateur de division ( /
) est automatiquement arrondi au nombre entier inférieur le plus proche. Par exemple:
25/10; // → 2.5
25n / 10n; // → 2n
Conversion de type implicite
Etant donné que la conversion de type implicite peut perdre des informations, les opérations mixtes entre BigInt
et Nombre
ne sont pas autorisées. Lors du mélange de grands nombres entiers et de nombres à virgule flottante, la valeur résultante peut ne pas être représentée avec précision par BigInt
ou Number
. Prenons l'exemple suivant:
(9007199254740992n + 1n) + 0.5
Le résultat de cette expression est en dehors du domaine des deux BigInt
et du Number
. A Le numéro
avec une partie décimale ne peut pas être converti avec précision en un BigInt
. Et un BigInt
supérieur à 2 53 ne peut pas être converti avec précision en un numéro
.
En raison de cette restriction, il est impossible d'effectuer des opérations arithmétiques. avec un mélange d'opérandes Number
et BigInt
. Vous ne pouvez pas non plus transmettre un BigInt
aux API Web et aux fonctions JavaScript intégrées qui attendent un numéro
. Si vous tentez de le faire, un TypeError
:
10 + 10n; // → TypeError
Math.max (2n, 4n, 6n); // → TypeError
Notez que les opérateurs relationnels ne suivent pas cette règle, comme le montre cet exemple:
10n> 5; // → true
Si vous souhaitez effectuer des calculs arithmétiques avec BigInt
et Number
vous devez d'abord déterminer le domaine dans lequel l'opération doit être effectuée. Pour cela, convertissez simplement l'un des opérandes en appelant Number ()
ou BigInt ()
:
BigInt (10) + 10n; // → 20n
// ou
10 + nombre (10n); // → 20
Lorsqu'il est rencontré dans un contexte booléen
BigInt
est traité de la même manière que Number
. En d'autres termes, un BigInt
est considéré comme une valeur de vérité tant qu'il n'est pas 0n
:
si (5n) {
// ce bloc de code sera exécuté
}
si (0n) {
// mais ce bloc de code ne le fera pas
}
Aucune conversion implicite de type n'a lieu lors du tri d'un tableau de BigInt
s et de Number
s:
const arr = [3n, 4, 2, 1n, 0, -1n];
arr.sort (); // → [-1n, 0, 1n, 2, 3n, 4]
Exploitants binaires tels que |
&
<<
>>
et ^
fonctionnent sur BigInt
de manière similaire à Number
s. Les nombres négatifs sont interprétés comme un complément de longueur infinie deux. Les opérandes mixtes ne sont pas autorisés. Voici quelques exemples:
90 | 115; // → 123
90n | 115n; // → 123n
90n | 115; // → TypeError
Le constructeur BigInt
Comme pour les autres types primitifs, un BigInt
peut être créé à l'aide d'une fonction constructeur. L'argument passé à BigInt ()
est automatiquement converti en un BigInt
si possible:
BigInt ("10"); // → 10n
BigInt (10); // → 10n
BigInt (true); // → 1n
Les types de données et les valeurs qui ne peuvent pas être converties jettent une exception:
BigInt (10.2); // → RangeError
BigInt (null); // → TypeError
BigInt ("abc"); // → SyntaxError
Vous pouvez effectuer directement des opérations arithmétiques sur un BigInt
créé à l'aide d'un constructeur:
BigInt (10) * 10n; // → 100n
Lorsqu'ils sont utilisés en tant qu'opérandes de l'opérateur d'égalité stricte, les BigInt
créés à l'aide d'un constructeur sont traités comme des opérateurs normaux:
BigInt (true) === 1n; // → true
Fonctions de bibliothèque
JavaScript fournit deux fonctions de bibliothèque pour représenter les valeurs BigInt
sous forme d'entiers signés ou non signés:
-
BigInt.asUintN (width, BigInt)
: enveloppe unBigInt
entre 0 et 2 width -1 -
BigInt.asInt (largeur, BigInt)
: enveloppe unBigInt
entre -2 width-1 et 2 width-1 -1
Ces fonctions sont particulièrement utiles pour les opérations arithmétiques sur 64 bits. Ainsi, vous pouvez rester dans la plage prévue.
Support et transcription du navigateur
Au moment de la rédaction de ce document, Chrome +67 et Opera +54 prennent entièrement en charge le type de données BigInt
. Malheureusement, Edge et Safari ne l’ont pas encore implémenté. Firefox ne prend pas en charge BigInt
par défaut, mais vous pouvez l'activer en définissant javascript.options.bigint
sur true
dans à propos de: config
. ]. Une liste à jour des navigateurs pris en charge est disponible sur Puis-je utiliser… .
Malheureusement, transpiler BigInt
est un processus extrêmement compliqué qui encourt une lourde pénalité de performance au moment de l'exécution. Il est également impossible de procéder directement à la polyfill BigInt
car la proposition modifie le comportement de plusieurs opérateurs existants. Pour le moment, une meilleure alternative consiste à utiliser la bibliothèque JSBI qui est une implémentation purement JavaScript de la proposition BigInt
.
Cette bibliothèque fournit une API qui se comporte exactement de la même manière. comme l'indigène BigInt
. Voici comment utiliser JSBI:
importer JSBI depuis './jsbi.mjs';
const b1 = JSBI.BigInt (Number.MAX_SAFE_INTEGER);
const b2 = JSBI.BigInt ('10 ');
const résultat = JSBI.add (b1, b2);
console.log (String (résultat)); // → '9007199254741001'
L’avantage d’utiliser JSBI est qu’une fois la prise en charge du navigateur améliorée, vous n’avez plus besoin de réécrire votre code. Au lieu de cela, vous pouvez compiler automatiquement votre code JSBI en code BigInt
natif à l’aide d’un plug-in babel . En outre, les performances de JSBI sont comparables à celles de l’application native BigInt
. Vous pouvez vous attendre à une prise en charge plus large du navigateur pour BigInt
Conclusion
BigInt
est un nouveau type de données destiné à être utilisé lorsque les valeurs entières sont supérieures à la plage prise en charge par Type de données Number
. Ce type de données nous permet d'effectuer en toute sécurité des opérations arithmétiques sur des entiers de grande taille, de représenter des horodatages à haute résolution, d'utiliser des identificateurs d'entiers de grande taille, etc. sans avoir besoin d'utiliser une bibliothèque.
Il est important de garder à l'esprit que vous ne pouvez pas effectuer d'opérations arithmétiques. avec un mélange d'opérandes Number
et BigInt
. Vous devrez déterminer le domaine dans lequel l'opération doit être effectuée en convertissant explicitement l'un des opérandes. De plus, pour des raisons de compatibilité, vous n'êtes pas autorisé à utiliser l'opérateur unaire plus ( +
) sur un BigInt
.
Qu'en pensez-vous? Trouvez-vous BigInt
utile? Faites-le nous savoir dans les commentaires!

Source link