BigInt is Coming

Catalogue
  1. 1. Number 的问题
  2. 2. 新的类型:BigInt
    1. 2.1. 当前状态
    2. 2.2. 特性
  3. 3. 参考资料

BigInt is Coming!

Number 的问题

JavaScript 里的 Number 是完全按照 IEEE Standard for Floating-Point Arithmetic (IEEE 754)[1,2] 实现的。Number 类型实际上就是 64 位浮点数(Double precision floating-point format),也就是俗称的 Double 类型。

任意数值都可以用科学计数法来表示,例如:

Double 类型数值的存储结构如下图所示,使用了64位二进制,最左边一位是符号位,之后11位是指数位,后面的52位是浮点数部分:

由于需要有很多位用来表示浮点数,因此 Double 类型所能够表示的整数范围远远小于 264

1
2
3
4
5
console.log(Number.MAX_SAFE_INTEGER);
// => 9007199254740991

Number.MAX_VALUE;
// => 1.7976931348623157e+308

尤其在到边界后,Double 类型表示的整数会出现不准的情况。例如:

1
14411518807585585000 + 1;  // 依然返回 14411518807585585000,意味着 1 是加不上去的

在跨语言的进程通信中,JavaScript Number 对整数的有限的支持常常会导致比较严重的问题,尤其在用户系统、交易系统里。int64(也被称为 long int)常常被用作用户ID,或者交易订单ID,前端 JS 在处理相关业务逻辑时,就不得不与后端约定使用字符串来表达 int64 类型。

新的类型:BigInt

当前状态

ECMAScript 为此提出的解决方案是引入新的基本类型:BigInt。在今年的 JSConf EU(欧洲 JavaScript 开发者大会)上,TC39 的成员做了一个对 BigInt 的介绍[4]

这个基本类型目前处在 Stage3 阶段。此阶段的含义是 Candidate(候选),“Indicate that further refinement will require feedback from implementations and users”,即需要实现者(通常是浏览器厂商)与用户进一步优化与反馈。

目前 Chrome67 已经开始支持 BigInt。还需要有至少一个其他浏览器厂商或JS运行时给出具体的实现。

特性

ECMAScript 的 BigInt 类型的值,字面量是直接在数字后面加小写字母 n

1
2
3
4
var a = 800n;
var b = 9007199254740991n;

a * b; // 返回 7205759403792792800n

这是继 string, number, boolean, null, undefined, symbol 这 6 个基本类型之后的又一个基本类型。意味着 typeof 运算符可以准确地判断相应值的类型。

1
typeof 2n;  // 输出 'bigint'

在进行数值计算时,NumberBigInt 之间没有隐式转换;但是布尔运算则可能会有隐式转换。

数值计算:

1
2
3
4
2 * 2n;
// 会直接报错:Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions

BigInt(2) * 2n; // 返回 4n

布尔运算:

1
2
2 == 2n;   // 返回 true
2 === 2n; // 返回 false,因为二者类型不相同

参考资料

  1. IEEE 754
  2. Double precision floating-point format(pdf)
  3. 双精度浮点运算指令.pdf
  4. BigInts in JavaScript: A case study in TC39
  5. Proposal: BigInt | tc39
Partager