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 | console.log(Number.MAX_SAFE_INTEGER); |
尤其在到边界后,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 | var a = 800n; |
这是继 string
, number
, boolean
, null
, undefined
, symbol
这 6 个基本类型之后的又一个基本类型。意味着 typeof
运算符可以准确地判断相应值的类型。
1 | typeof 2n; // 输出 'bigint' |
在进行数值计算时,Number
与 BigInt
之间没有隐式转换;但是布尔运算则可能会有隐式转换。
数值计算:
1 | 2 * 2n; |
布尔运算:
1 | 2 == 2n; // 返回 true |