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

浏览器兼容性

另见