BigInt

Baseline 已廣泛支援

此功能已成熟,並可在許多裝置和瀏覽器版本上使用。自 2020 年 9 月起,所有瀏覽器均已提供此功能。

BigInt 值表示的整數值,其大小 過大過小,無法用 number 原始型別 表示。

描述

BigInt 值,有時也簡稱為 BigInt,是一種 bigint 原始型別,可以透過在整數文字後面附加 n 來建立,或者透過呼叫 BigInt() 函式(不帶 new 運算子)併為其提供整數值或字串值來建立。

js
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"

js
typeof 1n === "bigint"; // true
typeof BigInt("1") === "bigint"; // true

BigInt 值也可以被包裝在 Object 中。

js
typeof Object(1n) === "object"; // true

運算子

大多數運算子支援 BigInt,但大多數不允許運算元是混合型別 — 兩個運算元都必須是 BigInt,或者都不是。

返回布林值的運算子允許混合數字和 BigInt 作為運算元。

有幾個運算子完全不支援 BigInt。

特殊情況

  • 涉及字串和 BigInt 的加法 (+) 會返回一個字串。
  • 除法 (/) 會將小數部分向零截斷,因為 BigInt 無法表示小數。
js
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 值不嚴格相等,但它們鬆散地相等。

js
0n === 0; // false
0n == 0; // true

Number 值和 BigInt 值可以按通常方式進行比較。

js
1n < 2; // true
2n > 1; // true
2 > 2; // false
2n > 2; // false
2n >= 2; // true

BigInt 值和 Number 值可以混合在陣列中並進行排序。

js
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 值進行比較的行為與其他物件一樣,僅當比較相同的物件例項時才表示相等。

js
Object(0n) === 0n; // false
Object(0n) === Object(0n); // false

const o = Object(0n);
o === o; // true

由於在 Number 值和 BigInt 值之間進行轉換可能導致精度損失,因此建議如下:

  • 僅當預期值大於 253 時才使用 BigInt 值。
  • 不要在 BigInt 值和 Number 值之間進行轉換。

條件請求

BigInt 值在以下情況下遵循與 Number 相同的轉換規則:

具體來說,只有 0n假值;其他所有值都是真值

js
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 ** 65537n17n ** 9999n 之間經過的時間差異,並根據經過的時間推斷秘密(如私鑰)的大小。如果您仍需要使用 BigInt,請參閱時序攻擊 FAQ 以獲取關於此問題的通用建議。

在 JSON 中使用

使用 JSON.stringify() 處理任何 BigInt 值都會引發 TypeError,因為 BigInt 值預設不會被序列化到 JSON。但是,JSON.stringify() 為 BigInt 值提供了一個後門:它會嘗試呼叫 BigInt 的 toJSON() 方法。(它不對任何其他原始值這樣做。)因此,您可以實現自己的 toJSON() 方法(這是為數不多的不明確反對修補內建物件的情況之一)。

js
BigInt.prototype.toJSON = function () {
  return { $bigint: this.toString() };
};

而不是丟擲錯誤,JSON.stringify() 現在會生成如下字串:

js
console.log(JSON.stringify({ a: 1n }));
// {"a":{"$bigint":"1"}}

如果您不想修補 BigInt.prototype,可以使用 JSON.stringifyreplacer 引數來序列化 BigInt 值。

js
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.parsereviver 引數來處理它們。

js
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 按原樣返回。
  • undefinednull 會丟擲 TypeError
  • true 轉換為 1nfalse 轉換為 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() 以及 BigInt64ArrayBigUint64Array 的方法。

建構函式

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() 方法。

示例

計算素數

js
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

瀏覽器相容性

另見