BigInt
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since September 2020.
BigInt
值代表数值,而 太大了 则由 number
、primitive 代表。
¥**BigInt
** values represent numeric values which are too large to be represented by the number
primitive.
描述
¥Description
BigInt 值(有时也简称为 BigInt)是 bigint
primitive,通过将 n
附加到整数文字的末尾,或通过调用 BigInt()
函数(不带 new
运算符)并为其指定整数值或字符串值来创建。
¥A BigInt value, also sometimes just called a BigInt, is a bigint
primitive, created by appending n
to the end of an integer literal, or by calling the BigInt()
function (without the new
operator) and giving it an integer value or string value.
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 值时可能会丢失精度。
¥BigInt values are similar to Number values in some ways, but also differ in a few key matters: A BigInt value cannot be used with methods in the built-in Math
object and cannot be mixed with a Number value in operations; they must be coerced to the same type. Be careful coercing values back and forth, however, as the precision of a BigInt value may be lost when it is coerced to a Number value.
类型信息
¥Type information
当针对 typeof
进行测试时,BigInt 值(bigint
原语)将给出 "bigint"
:
¥When tested against typeof
, a BigInt value (bigint
primitive) will give "bigint"
:
typeof 1n === "bigint"; // true
typeof BigInt("1") === "bigint"; // true
BigInt 值也可以封装在 Object
中:
¥A BigInt value can also be wrapped in an Object
:
typeof Object(1n) === "object"; // true
运算符
¥Operators
大多数运算符都支持 BigInt,但是大多数运算符不允许操作数为混合类型 - 两个操作数都必须是 BigInt 或都不是:
¥Most operators support BigInts, however most do not permit operands to be of mixed types — both operands must be BigInt or neither:
布尔返回运算符允许混合数字和 BigInt 作为操作数:
¥The boolean-returning operators allow mixing numbers and BigInts as operands:
- 关系运算符 和 相等运算符:
>
,<
,>=
,<=
,==
,!=
,===
,!==
- 逻辑运算符 仅依赖于操作数的 truthiness
有几个运算符根本不支持 BigInt:
¥A couple of operators do not support BigInt at all:
- 由于 asm.js 中的使用冲突,无法支持 一元加 (
+
),因此已将 为了不破坏 asm.js 排除在外。 - 无符号右移 (
>>>
) 是唯一不支持的按位运算符,因为每个 BigInt 值都是有符号的。
特别案例:
¥Special cases:
- 涉及字符串和 BigInt 的加法 (
+
) 返回字符串。 - 除法 (
/
) 将小数部分截断为零,因为 BigInt 无法表示小数。
const previousMaxSafe = BigInt(Number.MAX_SAFE_INTEGER); // 9007199254740991n
const maxPlusOne = previousMaxSafe + 1n; // 9007199254740992n
const theFuture = previousMaxSafe + 2n; // 9007199254740993n, this works now!
const multi = previousMaxSafe * 2n; // 18014398509481982n
const subtr = multi - 10n; // 18014398509481972n
const mod = multi % 10n; // 2n
const bigN = 2n ** 54n; // 18014398509481984n
bigN * -1n; // -18014398509481984n
const expected = 4n / 2n; // 2n
const truncated = 5n / 2n; // 2n, not 2.5n
比较
¥Comparisons
BigInt 值并不严格等于 Number 值,但大致如此:
¥A BigInt value is not strictly equal to a Number value, but it is loosely so:
0n === 0; // false
0n == 0; // true
Number 值和 BigInt 值可以像平常一样进行比较:
¥A Number value and a BigInt value may be compared as usual:
1n < 2; // true
2n > 1; // true
2 > 2; // false
2n > 2; // false
2n >= 2; // true
BigInt 值和 Number 值可以在数组中混合并排序:
¥BigInt values and Number values may be mixed in arrays and sorted:
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 值的比较与其他对象的比较一样,仅在比较同一对象实例时指示相等:
¥Note that comparisons with Object
-wrapped BigInt values act as with other objects, only indicating equality when the same object instance is compared:
Object(0n) === 0n; // false
Object(0n) === Object(0n); // false
const o = Object(0n);
o === o; // true
由于 Number 值和 BigInt 值之间的强制转换可能会导致精度损失,因此建议采用以下方法:
¥Because coercing between Number values and BigInt values can lead to loss of precision, the following are recommended:
- 仅当合理预期值大于 253 时才使用 BigInt 值。
- 不要在 BigInt 值和 Number 值之间进行强制转换。
条件句
¥Conditionals
在以下情况下,BigInt 值遵循与 Number 相同的转换规则:
¥A BigInt value follows the same conversion rules as Numbers when:
¥Namely, only 0n
is falsy; everything else is truthy.
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
密码学
¥Cryptography
BigInt 值支持的操作不是恒定时间的,因此对 定时攻击 开放。因此,如果没有缓解因素,JavaScript BigInts 在密码学中使用可能会很危险。作为一个非常通用的示例,攻击者可以测量 101n ** 65537n
和 17n ** 9999n
之间的时间差,并根据经过的时间推断出秘密(例如私钥)的大小。如果你仍然需要使用 BigInts,请查看 定时攻击常见问题解答 以获取有关该问题的一般建议。
¥The operations supported on BigInt values are not constant-time and are thus open to timing attacks. JavaScript BigInts therefore could be dangerous for use in cryptography without mitigating factors. As a very generic example, an attacker could measure the time difference between 101n ** 65537n
and 17n ** 9999n
, and deduce the magnitude of secrets, such as private keys, based on the time elapsed. If you still have to use BigInts, take a look at the Timing attack FAQ for general advice regarding the issue.
在 JSON 中使用
¥Use within JSON
将 JSON.stringify()
与任何 BigInt 值一起使用都会引发 TypeError
,因为默认情况下 BigInt 值不会在 JSON 中序列化。然而,JSON.stringify()
专门为 BigInt 值留下了后门:它会尝试调用 BigInt 的 toJSON()
方法。(它不会对任何其他原始值执行此操作。)因此,你可以实现自己的 toJSON()
方法(这是不明确阻止修补内置对象的少数情况之一):
¥Using JSON.stringify()
with any BigInt value will raise a TypeError
, as BigInt values aren't serialized in JSON by default. However, JSON.stringify()
specifically leaves a backdoor for BigInt values: it would try to call the BigInt's toJSON()
method. (It doesn't do so for any other primitive values.) Therefore, you can implement your own toJSON()
method (which is one of the few cases where patching built-in objects is not explicitly discouraged):
BigInt.prototype.toJSON = function () {
return { $bigint: this.toString() };
};
JSON.stringify()
现在不再抛出异常,而是生成如下字符串:
¥Instead of throwing, JSON.stringify()
now produces a string like this:
console.log(JSON.stringify({ a: 1n }));
// {"a":{"$bigint":"1"}}
如果你不想修补 BigInt.prototype
,可以使用 JSON.stringify
的 replacer
参数来序列化 BigInt 值:
¥If you do not wish to patch BigInt.prototype
, you can use the replacer
parameter of JSON.stringify
to serialize BigInt values:
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
参数来处理它们:
¥You can then use the reviver
parameter of JSON.parse
to handle them:
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()
的替换程序通用并正确序列化所有对象的 BigInt 值(如上所示),但必须谨慎使用JSON.parse()
的恢复程序,因为序列化是有损的:无法区分恰好具有名为$bigint
的属性的对象和实际的 BigInt。¥Note: While it's possible to make the replacer of
JSON.stringify()
generic and properly serialize BigInt values for all objects as shown above, the reviver ofJSON.parse()
has to be used with caution, because the serialization is lossy: it's not possible to distinguish between an object that happens to have a property called$bigint
and an actual BigInt.此外,上面的示例在替换和恢复期间创建了整个对象,这可能会对包含许多 BigInt 的较大对象产生性能或存储影响。如果你知道有效负载的形状,最好将它们序列化为字符串并根据属性键的名称恢复它们。
¥In addition, the example above creates an entire object during replacing and reviving, which may have performance or storage implications for larger objects containing many BigInts. If you know the shape of the payload, it may be better to just serialize them as strings and revive them based on the property key's name instead.
事实上,JSON 允许任意长的数字文字;它们只是无法在 JavaScript 中被完全精确地解析。如果你正在使用支持较长整数(例如 64 位整数)的语言与另一个程序进行通信,并且你希望将 BigInt 作为 JSON 数字而不是 JSON 字符串进行传输,请参阅 无损数字序列化。
¥In fact, JSON allows number literals that are arbitrarily long; they just cannot be parsed to full precision in JavaScript. If you are communicating with another program in a language that supports longer integers (such as 64-bit integers), and you want to transmit the BigInt as a JSON number instead of a JSON string, see Lossless number serialization.
BigInt 强制转换
¥BigInt coercion
许多期望 BigInts 的内置操作首先将其参数强制为 BigInts。操作 可概括如下:
¥Many built-in operations that expect BigInts first coerce their arguments to BigInts. The operation can be summarized as follows:
- BigInt 按原样返回。
undefined
和null
投掷TypeError
。true
变成1n
;false
变成0n
。- 通过解析字符串来转换它们,就好像它们包含整数文字一样。任何解析失败都会导致
SyntaxError
。该语法是 字符串数字文字 的子集,其中不允许使用小数点或指数指示符。 - 数字 抛出
TypeError
以防止意外的隐式强制转换导致精度损失。 - 符号 扔
TypeError
。 - 对象首先通过按顺序调用
[Symbol.toPrimitive]()
(以"number"
作为提示)、valueOf()
和toString()
方法来实现 转换为原始类型。然后将生成的原语转换为 BigInt。
在 JavaScript 中实现几乎相同效果的最佳方法是通过 BigInt()
函数:BigInt(x)
使用相同的算法来转换 x
,只是 数字 不会抛出 TypeError
,但如果它们是整数,则会转换为 BigInt。
¥The best way to achieve nearly the same effect in JavaScript is through the BigInt()
function: BigInt(x)
uses the same algorithm to convert x
, except that Numbers don't throw a TypeError
, but are converted to BigInts if they are integers.
请注意,需要 BigInt 的内置操作通常会在强制转换后将 BigInt 截断为固定宽度。这包括 BigInt.asIntN()
、BigInt.asUintN()
以及 BigInt64Array
和 BigUint64Array
的方法。
¥Note that built-in operations expecting BigInts often truncate the BigInt to a fixed width after coercion. This includes BigInt.asIntN()
, BigInt.asUintN()
, and methods of BigInt64Array
and BigUint64Array
.
构造函数
静态方法
¥Static methods
BigInt.asIntN()
-
将 BigInt 值钳位为有符号整数值,并返回该值。
BigInt.asUintN()
-
将 BigInt 值钳位为无符号整数值,并返回该值。
实例属性
¥Instance properties
这些属性在 BigInt.prototype
上定义并由所有 BigInt
实例共享。
¥These properties are defined on BigInt.prototype
and shared by all BigInt
instances.
BigInt.prototype.constructor
-
创建实例对象的构造函数。对于
BigInt
实例,初始值为BigInt
构造函数。 BigInt.prototype[Symbol.toStringTag]
-
[Symbol.toStringTag]
属性的初始值为字符串"BigInt"
。该属性在Object.prototype.toString()
中使用。但是,由于BigInt
也有自己的toString()
方法,因此除非你使用 BigInt 作为thisArg
调用Object.prototype.toString.call()
,否则不会使用此属性。
实例方法
¥Instance methods
BigInt.prototype.toLocaleString()
-
返回一个字符串,其中包含此 BigInt 值的语言敏感表示形式。覆盖
Object.prototype.toLocaleString()
方法。 BigInt.prototype.toString()
-
返回表示指定基数(基数)中的 BigInt 值的字符串。覆盖
Object.prototype.toString()
方法。 BigInt.prototype.valueOf()
-
返回此 BigInt 值。覆盖
Object.prototype.valueOf()
方法。
示例
计算素数
¥Calculating Primes
// Returns true if the passed BigInt value is a prime number
function isPrime(p) {
for (let i = 2n; i * i <= p; i++) {
if (p % i === 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
规范
Specification |
---|
ECMAScript Language Specification # sec-bigint-objects |
浏览器兼容性
BCD tables only load in the browser
也可以看看
¥See also