这是我参与11月更文挑战的第24天,活动详情查看:2021最后一次更文挑战
问题
面试官:你能讲讲es6新增的BigInt类型吗?
面试者:可以,这个主要是用来解决js超出最大精度后不准的问题。
面试官:js最大精度是多少?为什么不准?
面试者:巴拉巴拉小魔仙。。。
面试官:好的,你被录取了
以上场景纯属虚构哈。
今天来学学新增的BigInt类型。
BigInt
之前我们讲了js的精度问题,因为我们尾数部分只有52位,再加上隐藏的整数位,所以总共有53位。
然后最大精度的整数是Math.pow(2, 53) - 1, 超过的话js就不能保证准确了,比如:
Math.pow(2, 53) === Math.pow(2, 53) + 1 // true
console.log(90071992547409998) // 90071992547410000
定义
为了能准确表示最大精度以外的数,es6新增了BigInt类型,直译过来就是大整数。
BigInt的写法是数字后面再加上n。它的数据类型是bigint。
注意:只有整数才能加
n。小数会报错。同时不能直接带+
var num = 123n
typeof num // 'bigint'
90071992547409998n // 90071992547409998n
console.log(0.1n) // error: Invalid or unexpected token
console.log(+1n) // error: Cannot convert a BigInt value to a number
它可以直接进行运算(加法,乘法,减法,除法等)
注意:除法运算,如果结果有小数,会被舍弃小数部分。
var num = 3n
var num1 = 2n
console.log(num + num1) // 5n
console.log(num * num1) // 6n
console.log(num / num1) // 1n
BigInt函数
全局提供了一个BigInt函数,可以方便把其它类型转成BigInt类型。
console.log(BigInt(123)) // 123n
console.log(BigInt(true)) // 1n
console.log(BigInt('123')) // 123n
参数必填,而且参数必须是可以转成数字的,不然会报错。
console.log(BigInt('aaa')) // error: Cannot convert aaa to a BigInt
console.log(BigInt(undefined)) // error
console.log(BigInt(null)) // error
console.log(BigInt()) // error
它有2个静态方法
BigInt.asUintN(width, bigInt)
把给定的bigInt转成范围在0 到 2^width -1的bigInt值。如果bigInt不在这个范围则不能正确返回。
var num = 2n ** 64n
console.log(BigInt.asUintN(64, num - 1n)) // 18446744073709551615n
console.log(BigInt.asUintN(64, num)) // 0n
console.log(BigInt.asUintN(64, -1n)) // 18446744073709551615n
BigInt.asIntN(width, bigInt)
把给定的bigInt转成范围在 -2^(width -1)到 2^(width -1)-1的bigInt值。如果bigInt不在这个范围则不能正确返回。
console.log(BigInt.asIntN(64, -1n)) // -1n
var num = 2n ** (64n -1n)
console.log(BigInt.asIntN(64, num - 1n)) // 9223372036854775807n
console.log(BigInt.asIntN(64, num)) // -9223372036854775808n
其它
bigInt也可以转化其它类型
'' + 1n // "1"
String(1n) // "1"
Number(1n) // 1
Boolean(1n) // true
if语句也会转成对应的布尔型。
if(1n) // true
if(0n) // false
如果后台返回的数据已经超出最大安全整数,需要后台先把它转成bigInt类型再返回,不然我们拿到的时候已经是不准确的数值了。