BigInt了解一下

1,788 阅读4分钟

一、简介

BigInt 是一种内置对象,它提供了一种方法来表示大于 2^53-1的整数。这原本是 Javascript 中可以用 Number 表示的最大数字。BigInt 可以表示任意大的整数。- MDN

从上面的描述可以看出:

  • BigInt 用来描述的是整数
  • 它填补了 Number 在整数范围上的表示空缺

查看兼容性: caniuse

二、大数问题

在Javascript中,按照 IEEE 754-2008 标准的定义,所有数字都以 双精度64位浮点格式 表示。

在此标准下,JS 中的Number类型只能安全地表示 -9007199254740991 (-(2^53-1))9007199254740991(2^53-1) 之间的整数,任何超出此范围的整数值都可能失去精度。

// 最大安全整数
console.log(Number.MAX_SAFE_INTEGER); // → 9007199254740991
// 最小安全整数
console.log(Number.MIN_SAFE_INTEGER); // → -9007199254740991

// 失去精度-超过最大安全整数
console.log(9999999999999999);    // → 10000000000000000

// 注意最后一位的数字
9007199254740992 === 9007199254740993;    // → true

// 失去精度-超过最小安全整数
const minInt = Number.MIN_SAFE_INTEGER;
console.log(minInt);         // → -9007199254740991
console.log(minInt - 5);     // → -9007199254740996
// notice how this outputs the same value as above
console.log(minInt - 4);     // → -9007199254740996

三、解决方案

为了解决这些限制,一些JS开发人员使用字符串类型表示大整数。 例如,Twitter API 在使用 JSON 进行响应时会向对象添加字符串版本的 ID。 此外,还开发了许多库,例如 bignumber.js,以便更容易地处理大整数。

使用BigInt,应用程序不再需要变通方法或库来安全地表示 Number.MAX_SAFE_INTEGERNumber.Min_SAFE_INTEGER 之外的整数。 现在可以在标准JS中执行对大整数的算术运算,而不会有精度损失的风险。

要创建BigInt,只需在整数的末尾追加n即可。比较:

console.log(9007199254740995n);    // → 9007199254740995n
console.log(9007199254740995);     // → 9007199254740996

四、BigInt基础用法

创建

// 方式一:加n
console.log(1n); // → 1n
// 方式二:使用构造函数 BigInt
console.log(BigInt(1)); // → 1n

1n === BigInt(1) // → true
typeof 1n; // → bigint

使用构造函数创建时,传递给 BigInt() 的参数将自动转换为 BigInt

BigInt(10); // → 10n
BigInt('10'); // → 10n
BigInt(true); // → 1n

无法转换的数据类型和值会引发异常:

BigInt(10.2);     // → RangeError
BigInt(null);     // → TypeError
BigInt("abc");    // → SyntaxError

运算

除一元加号 (+) 运算符外,所有算术运算符都可用于 BigInt

10n + 20n;    // → 30n
10n - 20n;    // → -10n
+10n;         // → TypeError: Cannot convert a BigInt value to a number
-10n;         // → -10n
10n * 20n;    // → 200n
20n / 10n;    // → 2n
23n % 10n;    // → 3n
10n ** 3n;    // → 1000n

const x = 10n;
++x;          // → 11n
--x;          // → 9n

不支持一元加号(+)运算符的原因是某些程序可能依赖于 + 始终生成 Number 的不变量,或者抛出异常。 更改 + 的行为也会破坏asm.js代码。

当然,与BigInt操作数一起使用时,算术运算符应该返回 BigInt 值。因此,除法 (/) 运算符的结果会自动向下舍入到最接近的整数。例如:

25 / 10;      // → 2.5
25n / 10n;    // → 2n

因为隐式类型转换可能丢失信息,所以 BigIntNumber 之间不能直接进行运算:

10 + 10n;    // → TypeError
Math.max(2n, 4n, 6n);    // → TypeError

关系运算符不受此影响:

10n > 5; // → true

如果希望使用 BigInt Number 执行算术计算,首先需要确定应该在哪个类型中执行该操作。为此,只需通过调用 Number()BigInt() 来转换操作数:

BigInt(10) + 10n;    // → 20n
// or
10 + Number(10n);    // → 20

Boolean 类型与 BigInt 类型相遇时,BigInt 的处理方式与 Number 类似,换句话说,只要不是 0nBigInt 就被视为 truthy 的值:

if (5n) {
    // 这里代码块将被执行
}

if (0n) {
    // 这里代码块不会执行
}

总结

BigInt 是一种新的基础数据类型,它的出现填补了JS在大数表达和运算上的空缺,在使用大整数id等场景时,不再需要使用库。

主要注意的是,不能直接拿 NumberBigInt 进行运算,而需要先显示转换其中的一种类型。另外,由于兼容性的问题,不能再 BigInt 上使用一元加号 (+) 运算符。

参考

A Guide to BigInt: JavaScript’s Newest Data Type

🎈感谢您的阅读,欢迎按赞留言~