BigInt
描述
BigInt 值,有時也簡稱為 BigInt,是一種 bigint 原始型別,可以透過在整數文字後面附加 n 來建立,或者透過呼叫 BigInt() 函式(不帶 new 運算子)併為其提供整數值或字串值來建立。
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 值在某些方面與 Number 值相似,但在一些關鍵方面也有所不同:BigInt 值不能與內建 Math 物件中的方法一起使用,也不能與 Number 值在操作中混合;它們必須被強制轉換為相同型別。但是,在來回強制轉換值時要小心,因為 BigInt 值在強制轉換為 Number 值時可能會丟失精度。
型別資訊
當使用 typeof 進行測試時,BigInt 值(bigint 原始型別)將返回 "bigint"。
typeof 1n === "bigint"; // true
typeof BigInt("1") === "bigint"; // true
BigInt 值也可以被包裝在 Object 中。
typeof Object(1n) === "object"; // true
運算子
大多數運算子支援 BigInt,但大多數不允許運算元是混合型別 — 兩個運算元都必須是 BigInt,或者都不是。
返回布林值的運算子允許混合數字和 BigInt 作為運算元。
有幾個運算子完全不支援 BigInt。
- 一元加號 (
+) 由於與 asm.js 的用法衝突而無法支援,因此被省略了,以避免破壞 asm.js。 - 無符號右移 (
>>>) 是唯一不受支援的位運算子,因為每個 BigInt 值都是有符號的。
特殊情況
- 涉及字串和 BigInt 的加法 (
+) 會返回一個字串。 - 除法 (
/) 會將小數部分向零截斷,因為 BigInt 無法表示小數。
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
比較
BigInt 值與 Number 值不嚴格相等,但它們鬆散地相等。
0n === 0; // false
0n == 0; // true
Number 值和 BigInt 值可以按通常方式進行比較。
1n < 2; // true
2n > 1; // true
2 > 2; // false
2n > 2; // false
2n >= 2; // true
BigInt 值和 Number 值可以混合在陣列中並進行排序。
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 ]
請注意,與 Object 包裝的 BigInt 值進行比較的行為與其他物件一樣,僅當比較相同的物件例項時才表示相等。
Object(0n) === 0n; // false
Object(0n) === Object(0n); // false
const o = Object(0n);
o === o; // true
由於在 Number 值和 BigInt 值之間進行轉換可能導致精度損失,因此建議如下:
- 僅當預期值大於 253 時才使用 BigInt 值。
- 不要在 BigInt 值和 Number 值之間進行轉換。
條件請求
BigInt 值在以下情況下遵循與 Number 相同的轉換規則:
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
密碼學
在 BigInt 值上支援的操作不是恆定時間的,因此容易受到時序攻擊。因此,JavaScript BigInts 在沒有緩解因素的情況下可能不適合用於加密。作為一個非常通用的例子,攻擊者可以測量 101n ** 65537n 和 17n ** 9999n 之間經過的時間差異,並根據經過的時間推斷秘密(如私鑰)的大小。如果您仍需要使用 BigInt,請參閱時序攻擊 FAQ 以獲取關於此問題的通用建議。
在 JSON 中使用
使用 JSON.stringify() 處理任何 BigInt 值都會引發 TypeError,因為 BigInt 值預設不會被序列化到 JSON。但是,JSON.stringify() 為 BigInt 值提供了一個後門:它會嘗試呼叫 BigInt 的 toJSON() 方法。(它不對任何其他原始值這樣做。)因此,您可以實現自己的 toJSON() 方法(這是為數不多的不明確反對修補內建物件的情況之一)。
BigInt.prototype.toJSON = function () {
return { $bigint: this.toString() };
};
而不是丟擲錯誤,JSON.stringify() 現在會生成如下字串:
console.log(JSON.stringify({ a: 1n }));
// {"a":{"$bigint":"1"}}
如果您不想修補 BigInt.prototype,可以使用 JSON.stringify 的 replacer 引數來序列化 BigInt 值。
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"}}
然後,您可以使用 JSON.parse 的 reviver 引數來處理它們。
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 }
注意:雖然可以透過使 JSON.stringify() 的 replacer 通用並正確序列化所有物件的 BigInt 值(如上所示),但 JSON.parse() 的 reviver 必須謹慎使用,因為序列化是不可逆的:無法區分一個碰巧具有名為 $bigint 屬性的物件和一個實際的 BigInt。
此外,上面的示例在替換和恢復過程中建立了一個完整的物件,這可能對包含許多 BigInt 的大型物件產生效能或儲存影響。如果您知道 payload 的形狀,則最好將其序列化為字串,然後根據屬性鍵的名稱進行恢復。
事實上,JSON 允許任意長度的數字文字;只是它們無法在 JavaScript 中被解析為完整精度。如果您正在與支援更長整數(如 64 位整數)的另一種語言的程式進行通訊,並且希望將 BigInt 作為 JSON 數字而不是 JSON 字串傳輸,請參閱 無損數字序列化。
BigInt 轉換
許多需要 BigInt 的內建操作會先將它們的引數轉換為 BigInt。該操作可總結如下:
- BigInts 按原樣返回。
undefined和null會丟擲TypeError。true轉換為1n;false轉換為0n。- 字串透過解析它們(就好像它們包含整數文字一樣)來轉換。任何解析失敗都會導致
SyntaxError。語法是字串數字字面量的一個子集,不允許使用小數點或指數指示符。 - Numbers 會丟擲
TypeError,以防止意外的隱式轉換導致精度損失。 - Symbols 會丟擲
TypeError。 - 物件首先透過呼叫其
[Symbol.toPrimitive]()(以"number"作為提示)、valueOf()和toString()方法(按此順序)轉換為原始型別。然後將生成的原始型別轉換為 BigInt。
在 JavaScript 中實現幾乎相同效果的最佳方法是透過 BigInt() 函式:BigInt(x) 使用相同的演算法來轉換 x,除了 Numbers 不會丟擲 TypeError,而是會在它們是整數時轉換為 BigInt。
請注意,需要 BigInt 的內建操作通常會在轉換後將 BigInt 截斷為固定寬度。這包括 BigInt.asIntN()、BigInt.asUintN() 以及 BigInt64Array 和 BigUint64Array 的方法。
建構函式
BigInt()-
返回型別為 BigInt 的原始值。使用
new呼叫時會丟擲錯誤。
靜態方法
BigInt.asIntN()-
將 BigInt 值鉗制到一個有符號整數值,並返回該值。
BigInt.asUintN()-
將 BigInt 值鉗制到一個無符號整數值,並返回該值。
例項屬性
這些屬性定義在 BigInt.prototype 上,並由所有 BigInt 例項共享。
BigInt.prototype.constructor-
建立例項物件的建構函式。對於
BigInt例項,初始值是BigInt建構函式。 BigInt.prototype[Symbol.toStringTag]-
[Symbol.toStringTag]屬性的初始值是字串"BigInt"。此屬性用於Object.prototype.toString()。但是,由於BigInt也有自己的toString()方法,因此除非使用 BigInt 作為thisArg呼叫Object.prototype.toString.call(),否則不會使用此屬性。
例項方法
BigInt.prototype.toLocaleString()-
返回一個具有此 BigInt 值語言敏感表示的字串。覆蓋
Object.prototype.toLocaleString()方法。 BigInt.prototype.toString()-
以指定的基數(基數)返回此 BigInt 值的字串表示形式。覆蓋
Object.prototype.toString()方法。 BigInt.prototype.valueOf()-
返回此 BigInt 值。覆蓋
Object.prototype.valueOf()方法。
示例
計算素數
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
注意:isPrime() 實現僅用於演示。對於實際應用,您需要使用高度記憶化的演算法,例如埃拉託斯特尼篩法,以避免重複計算。
規範
| 規範 |
|---|
| ECMAScript® 2026 語言規範 # sec-bigint-objects |
瀏覽器相容性
載入中…