记录开发过程中遇到的js超大number类型数字精度丢失问题

589 阅读2分钟

业务需求及问题现象描述

使用js的JSON.parse方法将json字符串转换为json对象时发现后端返回过来的是report_role_id":290872577328809008 使用JSON.parse方法数字转换精度问题的解决(数字过大尾数会变0)

问题现象截图

Screenshot 2023-01-27 at 00.05.59.png

问题类型

这是由于该数字超出了 Number.MAX_SAFE_INTEGER的最大安全范围导致的数字精度丢失问题,通常为-(2^53 - 1) 到 2^53 - 1` 之间的数值(包含边界值)。

解决方案

方案一

使用js新增数据类型BigInt解决该问题

可以用在一个整数字面量后面加 n 的方式定义一个 BigInt ,如:10n,或者调用函数 BigInt()(但不包含 new 运算符)并传递一个整数值或字符串值。

const theBiggestInt = 9007199254740991n;

const alsoHuge = BigInt(9007199254740991);
// ↪ 9007199254740991n

const hugeString = BigInt("9007199254740991");
// ↪ 9007199254740991n

const hugeHex = BigInt("0x1fffffffffffff");
// ↪ 9007199254740991n

const hugeBin = BigInt("0b11111111111111111111111111111111111111111111111111111");
// ↪ 9007199254740991n

优点:原生 API调用简单,无需借助第三方库

缺点:

  1. 兼容性问题,可以在can i use?上查看浏览器的兼容性如下图,chrome 67+,edge79+,safari14+,firefox68+,opera54+等版本浏览器才能够支持该类型

Screenshot 2023-01-28 at 14.37.41.png 2. 由于 Number 和 BigInt 之间的强制转换会导致精度损失,因此建议仅在合理预期大于 2^53 的值时才使用 BigInt,而不是在这两种类型之间进行强制转换。

方案二

使用bignumber.js等第三方库

这里对使用不再做过多的赘述,详情可以参考官方文档

优点:

  1. 更加友好的兼容性
  2. API简单功能齐全

缺点:

需要而外安装依赖包,虽然只有约8kb

方案三

与后端沟通协商将此超长number改为string类型返回给前端