BigInt
Baseline
Weitgehend verfügbar
Diese Funktion ist gut etabliert und funktioniert auf vielen Geräten und in vielen Browserversionen. Sie ist seit September 2020 browserübergreifend verfügbar.
BigInt-Werte repräsentieren ganzzahlige Werte, die zu hoch oder zu niedrig sind, um durch den number- Primitiv repräsentiert zu werden.
Beschreibung
Ein BigInt-Wert, manchmal auch einfach BigInt genannt, ist ein bigint- Primitiv, das durch Anhängen von n an das Ende eines Ganzzahlen-Literals erstellt wird oder durch Aufruf der BigInt()-Funktion (ohne den new-Operator) und Übergabe eines Ganzzahlen- oder String-Werts.
const previouslyMaxSafeInteger = 9007199254740991n;
const alsoHuge = BigInt(9007199254740991);
// 9007199254740991n
const hugeString = BigInt("9007199254740991");
// 9007199254740991n
const hugeHex = BigInt("0x1fffffffffffff");
// 9007199254740991n
const hugeOctal = BigInt("0o377777777777777777");
// 9007199254740991n
const hugeBin = BigInt(
"0b11111111111111111111111111111111111111111111111111111",
);
// 9007199254740991n
BigInt-Werte ähneln in einigen Punkten den Nummernwerten, unterscheiden sich jedoch auch in einigen wesentlichen Aspekten: Ein BigInt-Wert kann nicht mit Methoden des eingebauten Math-Objekts verwendet und nicht mit einem Nummernwert in Operationen gemischt werden; sie müssen auf den gleichen Typ gezwungen werden. Seien Sie jedoch vorsichtig beim Konvertieren von Werten hin und her, da die Genauigkeit eines BigInt-Werts verloren gehen kann, wenn er in einen Nummernwert umgewandelt wird.
Typinformationen
Wenn ein BigInt-Wert (das bigint-Primitiv) mit typeof geprüft wird, wird "bigint" zurückgegeben:
typeof 1n === "bigint"; // true
typeof BigInt("1") === "bigint"; // true
Ein BigInt-Wert kann auch in ein Object eingebunden werden:
typeof Object(1n) === "object"; // true
Operatoren
Die meisten Operatoren unterstützen BigInts, jedoch erlauben die meisten keine Operanden gemischten Typs — beide Operanden müssen BigInt sein oder keiner:
- Arithmetische Operatoren:
+,-,*,/,%,** - Bitweise Operatoren:
>>,<<,&,|,^,~ - Unäre Negation (
-) - Inkrement/Dekrement:
++,--
Die Operatoren, die Boolean-Werte zurückgeben, erlauben das Mischen von Numbers und BigInts als Operanden:
- Relationale Operatoren und Gleichheitsoperatoren:
>,<,>=,<=,==,!=,===,!== - Logische Operatoren verlassen sich nur auf die Wahrhaftigkeit der Operanden
Einige Operatoren unterstützen BigInt überhaupt nicht:
- Unäres Plus (
+) kann nicht unterstützt werden aufgrund einer widersprüchlichen Nutzung in asm.js, daher wurde es weggelassen, um asm.js nicht zu stören. - Der Unsigned Right Shift (
>>>) ist der einzige bitweise Operator, der nicht unterstützt wird, da jeder BigInt-Wert vorzeichenbehaftet ist.
Spezialfälle:
- Addition (
+) mit einem String und einem BigInt gibt einen String zurück. - Division (
/) schneidet Bruchteile gegen null ab, da BigInt gebrochene Mengen nicht darstellen kann.
const previousMaxSafe = BigInt(Number.MAX_SAFE_INTEGER); // 9007199254740991n
const maxPlusOne = previousMaxSafe + 1n; // 9007199254740992n
const theFuture = previousMaxSafe + 2n; // 9007199254740993n, this works now!
const prod = previousMaxSafe * 2n; // 18014398509481982n
const diff = prod - 10n; // 18014398509481972n
const mod = prod % 10n; // 2n
const bigN = 2n ** 54n; // 18014398509481984n
bigN * -1n; // -18014398509481984n
const expected = 4n / 2n; // 2n
const truncated = 5n / 2n; // 2n, not 2.5n
Vergleiche
Ein BigInt-Wert ist nicht streng gleich einem Number-Wert, aber lose gleich:
0n === 0; // false
0n == 0; // true
Ein Number-Wert und ein BigInt-Wert können wie gewohnt verglichen werden:
1n < 2; // true
2n > 1; // true
2 > 2; // false
2n > 2; // false
2n >= 2; // true
BigInt-Werte und Number-Werte können in Arrays gemischt und sortiert werden:
const mixed = [4n, 6, -12n, 10, 4, 0, 0n];
// [4n, 6, -12n, 10, 4, 0, 0n]
mixed.sort(); // default sorting behavior
// [ -12n, 0, 0n, 10, 4n, 4, 6 ]
mixed.sort((a, b) => a - b);
// won't work since subtraction will not work with mixed types
// TypeError: can't convert BigInt value to Number value
// sort with an appropriate numeric comparator
mixed.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
// [ -12n, 0, 0n, 4n, 4, 6, 10 ]
Beachten Sie, dass Vergleiche mit Object-eingebundenen BigInt-Werten wie bei anderen Objekten nur dann Gleichheit anzeigen, wenn die gleiche Objektinstanz verglichen wird:
Object(0n) === 0n; // false
Object(0n) === Object(0n); // false
const o = Object(0n);
o === o; // true
Da das Konvertieren zwischen Number-Werten und BigInt-Werten zu einem Verlust der Genauigkeit führen kann, wird Folgendes empfohlen:
- Verwenden Sie einen BigInt-Wert nur, wenn Werte größer als 253 vernünftigerweise erwartet werden.
- Zwingen Sie keine Umwandlungen zwischen BigInt-Werten und Number-Werten.
Bedingte Anweisungen
Ein BigInt-Wert folgt denselben Konvertierungsregeln wie Numbers, wenn:
- es in einen
Booleanumgewandelt wird: über dieBoolean-Funktion; - wenn es mit logischen Operatoren
||,&&, und!verwendet wird; oder - innerhalb eines bedingten Tests wie einer
if-Anweisung.
Namentlich ist nur 0n falsch; alles andere ist wahr.
if (0n) {
console.log("Hello from the if!");
} else {
console.log("Hello from the else!");
}
// "Hello from the else!"
0n || 12n; // 12n
0n && 12n; // 0n
Boolean(0n); // false
Boolean(12n); // true
!12n; // false
!0n; // true
Kryptographie
Die auf BigInt-Werten unterstützten Operationen sind nicht konstanter Zeit und sind daher anfällig für Timing-Angriffe. JavaScript-BigInts könnten daher gefährlich für den Einsatz in der Kryptographie sein, wenn keine mildernden Maßnahmen ergriffen werden. Als sehr generisches Beispiel könnte ein Angreifer den Zeitunterschied zwischen 101n ** 65537n und 17n ** 9999n messen und die Größe von Geheimnissen, wie z.B. privaten Schlüsseln, basierend auf der verstrichenen Zeit ableiten. Wenn Sie dennoch BigInts verwenden müssen, werfen Sie einen Blick auf das Timing-Angriff-FAQ für allgemeine Ratschläge zu diesem Thema.
Verwendung innerhalb von JSON
Die Verwendung von JSON.stringify() mit einem beliebigen BigInt-Wert führt zu einem TypeError, da BigInt-Werte standardmäßig nicht in JSON serialisiert werden. JSON.stringify() lässt jedoch speziell ein Hintertürchen für BigInt-Werte offen: Es würde versuchen, die toJSON()-Methode des BigInt aufzurufen. (Dies tut es bei keinem anderen primitiven Wert.) Daher können Sie Ihre eigene toJSON()-Methode implementieren (was einer der wenigen Fälle ist, in denen das Patchen von eingebauten Objekten nicht ausdrücklich entmutigt wird):
BigInt.prototype.toJSON = function () {
return { $bigint: this.toString() };
};
Anstatt zu werfen, erzeugt JSON.stringify() jetzt einen String wie diesen:
console.log(JSON.stringify({ a: 1n }));
// {"a":{"$bigint":"1"}}
Wenn Sie BigInt.prototype nicht patchen möchten, können Sie den replacer-Parameter von JSON.stringify verwenden, um BigInt-Werte zu serialisieren:
const replacer = (key, value) =>
typeof value === "bigint" ? { $bigint: value.toString() } : value;
const data = {
number: 1,
big: 18014398509481982n,
};
const stringified = JSON.stringify(data, replacer);
console.log(stringified);
// {"number":1,"big":{"$bigint":"18014398509481982"}}
Sie können dann den reviver-Parameter von JSON.parse verwenden, um sie zu behandeln:
const reviver = (key, value) =>
value !== null &&
typeof value === "object" &&
"$bigint" in value &&
typeof value.$bigint === "string"
? BigInt(value.$bigint)
: value;
const payload = '{"number":1,"big":{"$bigint":"18014398509481982"}}';
const parsed = JSON.parse(payload, reviver);
console.log(parsed);
// { number: 1, big: 18014398509481982n }
Hinweis:
Obwohl es möglich ist, den Ersatz von JSON.stringify() generisch zu machen und BigInt-Werte für alle Objekte ordnungsgemäß zu serialisieren, muss der reviver von JSON.parse() mit Vorsicht verwendet werden, da die Serialisierung irreversibel ist: Es ist nicht möglich, zwischen einem Objekt, das zufällig eine Eigenschaft namens $bigint hat, und einem echten BigInt zu unterscheiden.
Außerdem erstellt das obige Beispiel während des Ersetzens und Wiederherstellens ein ganzes Objekt, was für größere Objekte, die viele BigInts enthalten, Leistungs- oder Speicherimplikationen haben kann. Wenn Sie die Form der Nutzlast kennen, ist es möglicherweise besser, sie einfach als Strings zu serialisieren und basierend auf dem Eigenschaftsname des Schlüssels wiederherzustellen.
Tatsächlich erlaubt JSON Zahlenliterale beliebiger Länge; sie können nur nicht mit voller Genauigkeit in JavaScript geparst werden. Wenn Sie mit einem anderen Programm in einer Sprache kommunizieren, die längere Ganzzahlen unterstützt (wie 64-Bit-Ganzzahlen) und Sie das BigInt als JSON-Zahl anstelle eines JSON-Strings übertragen möchten, siehe Verlustlose Zahlenserialization.
BigInt-Zwang
Viele integrierte Operationen, die BigInts erwarten, zwingen ihre Argumente zuerst zu BigInts. Die Operation kann wie folgt zusammengefasst werden:
- BigInts werden unverändert zurückgegeben.
undefinedundnullwerfen einenTypeError.truewird zu1n;falsewird zu0n.- Strings werden konvertiert, indem sie geparst werden, als ob sie ein Ganzzahlenliteral enthalten. Jegliches Parsing-Versagen führt zu einem
SyntaxError. Die Syntax ist ein Teilmengen von string numeric literals, bei denen Dezimalpunkte oder Exponentenindikatoren nicht erlaubt sind. - Numbers werfen einen
TypeError, um unbeabsichtigte implizite Umwandlungen, die zu Präzisionsverlust führen könnten, zu verhindern. - Symbole werfen einen
TypeError. - Objekte werden zuerst zu einem primitiven umgewandelt, indem ihre
[Symbol.toPrimitive]()(mit"number"als Hinweis),valueOf(), undtoString()-Methoden in dieser Reihenfolge aufgerufen werden. Das resultierende Primitive wird dann in ein BigInt umgewandelt.
Die beste Methode, um nahezu denselben Effekt in JavaScript zu erreichen, ist die Verwendung der BigInt()-Funktion: BigInt(x) verwendet denselben Algorithmus, um x zu konvertieren, außer dass Numbers keinen TypeError werfen, sondern in BigInts umgewandelt werden, wenn sie Ganzzahlen sind.
Beachten Sie, dass eingebaute Operationen, die BigInts erwarten, nach der Umwandlung das BigInt oft auf eine feste Breite kürzen. Dazu gehören BigInt.asIntN(), BigInt.asUintN(), und Methoden von BigInt64Array und BigUint64Array.
Konstruktor
BigInt()-
Gibt primitive Werte vom Typ BigInt zurück. Wirft einen Fehler, wenn er mit
newaufgerufen wird.
Statische Methoden
BigInt.asIntN()-
Kürzt einen
BigInt-Wert auf die angegebene Anzahl der signifikanten Bits und gibt diesen Wert als vorzeichenbehafteten Integer zurück. BigInt.asUintN()-
Kürzt einen
BigInt-Wert auf die angegebene Anzahl der signifikanten Bits und gibt diesen Wert als vorzeichenlosen Integer zurück.
Instanz-Eigenschaften
Diese Eigenschaften sind auf BigInt.prototype definiert und werden von allen BigInt-Instanzen geteilt.
BigInt.prototype.constructor-
Die Konstruktorfunktion, die das Instanzobjekt erstellt hat. Für
BigInt-Instanzen ist der Anfangswert derBigInt-Konstruktor. BigInt.prototype[Symbol.toStringTag]-
Der Anfangswert der
[Symbol.toStringTag]-Eigenschaft ist der String"BigInt". Diese Eigenschaft wird inObject.prototype.toString()verwendet. DaBigIntjedoch auch seine eigenetoString()-Methode hat, wird diese Eigenschaft nicht verwendet, es sei denn, Sie rufenObject.prototype.toString.call()mit einem BigInt alsthisArgauf.
Instanz-Methoden
BigInt.prototype.toLocaleString()-
Gibt einen String mit einer sprachensensitiven Darstellung dieses BigInt-Werts zurück. Überschreibt die
Object.prototype.toLocaleString()-Methode. BigInt.prototype.toString()-
Gibt einen String zurück, der diesen BigInt-Wert in der angegebenen Basis (Radix) darstellt. Überschreibt die
Object.prototype.toString()-Methode. BigInt.prototype.valueOf()-
Gibt diesen BigInt-Wert zurück. Überschreibt die
Object.prototype.valueOf()-Methode.
Beispiele
>Berechnung von Primzahlen
function isPrime(n) {
if (n < 2n) {
return false;
}
if (n % 2n === 0n) {
return n === 2n;
}
for (let factor = 3n; factor * factor <= n; factor += 2n) {
if (n % factor === 0n) {
return false;
}
}
return true;
}
// Takes a BigInt value as an argument, returns nth prime number as a BigInt value
function nthPrime(nth) {
let maybePrime = 2n;
let prime = 0n;
while (nth >= 0n) {
if (isPrime(maybePrime)) {
nth--;
prime = maybePrime;
}
maybePrime++;
}
return prime;
}
nthPrime(20n);
// 73n
Hinweis:
Die isPrime()-Implementierung ist nur zur Demonstration gedacht. Für eine reale Anwendung würden Sie einen stark optimierten Algorithmus wie das Sieb des Eratosthenes verwenden, um wiederholte Berechnungen zu vermeiden.
Spezifikationen
| Spezifikation |
|---|
| ECMAScript® 2027 Language Specification> # sec-bigint-objects> |