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 |
浏览器兼容性
加载中…