JavaScript基本数据类型“七兄弟”之老七——BigInt

1,403 阅读4分钟

ES10虽然还是一个草案,但是其中添加的一些特性给前端带来了巨大的变化,让js语言更加精进。今天我们就来聊一聊ES10的新特性之一 BigInt (任意精度整数)。

ES6之后JavaScript的基本数据类型增加到6种:

  • String
  • Number
  • Boolean
  • Undefiend
  • Null
  • Symbol。

目前BigInt还处于stage-4阶段,不出意外即将成为js的第七种基本数据类型和第二个数字数据类型。

问题

我们都知道在js中Number类型是按照按照IEEE754-2008标准的定义,所有数字都以双精度64位浮点格式表示,在此标准范围内,js的Number类型只能安全地表示-9007199254740991 (-(2^53-1)) 和9007199254740991(2^53-1)之间的整数,任何超出此范围的整数值都可能被自动四舍五入丢失精度。

意外的四舍五入精度丢失,有可能会对程序安全性造成损害,甚至对用户和公司造成财产损失。

在这里讨论这个问题也是因为确确实实踩到了这个坑,大概说一下问题,昨天晚上有用户反馈白名单设置有bug,造成部分白名单限制失效,然后就跟后端一起排查,最终定位到问题是:后端返回的白名单用户ID是数字类型,位数达到18位,早已超出了最大安全数9007199254740991,发生了精度丢失。

解决方案

相信大多数人应该都能想到,使用字符串类型表示大数,机智如我,最终我也是通过这种方式进行的紧急修复上线。业界也有成熟的方案库,以便更容易地处理大整数,例如,例如 bignumber.js

现在有了BigInt,所有比Number.MAX_SAFE_INTEGER大的数都可以不用再通过变通的方法和担心有精度丢失的风险。

语法

可以用在一个整数字面量后面加 n 的方式定义一个 BigInt ,如:10n,或者调用函数BigInt(value);value可以是数字或字符串

注意:Bigint不是构造函数,不能使用new 操作符。

类型信息

使用 typeof 测试时, BigInt 对象返回 "bigint"

typeof 123n === 'bigint'; // true
typeof BigInt('123') === 'bigint'; // true
123n == 123 // true

使用 Object 包装后, BigInt 被认为是一个普通 "object" :

typeof Object(123n) === 'object'; // true

运算

以下操作符可以和 BigInt 一起使用: +、*-**% 。除 >>> (无符号右移)之外的 位操作 也可以支持。因为 BigInt 都是有符号的, >>> (无符号右移)不能用于 BigInt。为了兼容 asm.js ,BigInt 不支持单目 (+) 运算符。

const previousMaxSafe = BigInt(Number.MAX_SAFE_INTEGER);
const maxPlusOne = previousMaxSafe + 1n; // 9007199254740992n
const multi = previousMaxSafe * 2n; //18014398509481982n
const mod = multi % 10n; // 2n

当使用 BigInt 时,带小数的运算会被取整

const expected = 4n / 2n; // 2
const rounded = 5n / 2n // 2

方法介绍

静态方法

BigInt.asIntN() : 将 BigInt 值转换为一个 -2width - 1 与 2width-1-1 之间的有符号整数。

BigInt.asUintN() : 将一个 BigInt 值转换为 0 与 2width-1 之间的无符号整数。

实例方法

BigInt.prototype.toLocaleString()

返回此数字的 language-sensitive 形式的字符串。覆盖 Object.prototype.toLocaleString() 方法。

BigInt.prototype.toString()

返回以指定基数(base)表示指定数字的字符串。覆盖 Object.prototype.toString() 方法。

BigInt.prototype.valueOf()

返回指定对象的基元值。 覆盖 Object.prototype.valueOf() 方法。

结尾

由于在 Number 与 BigInt 之间进行转换会损失精度,因而建议仅在值可能大于253 时使用 BigInt 类型,并且不在两种类型之间进行相互转换。

对任何 BigInt 值使用 JSON.stringify() 都会引发 TypeError,因为默认情况下 BigInt 值不会在 JSON 中序列化。

以上就是对于javaScript新基本类型Bigint的基本介绍,喜欢文章的小伙伴可以点赞,欢迎留言交流讨论!也欢迎大佬对文章中的错误进行斧正