前端大整数精度丢失:一次踩坑后的实战解决方案(`json-bigint`)

最近在项目里处理企业信息接口,遇到一个很隐蔽的问题:

后端返回的企业 ID 明明是一个值,前端拿到后却"变了"。这是前端把大整数精度丢了

这篇就聊三件事:为什么会丢、什么时候丢、怎么彻底规避。


先看现象:两个数相等?

js 复制代码
9007199254740992 === 9007199254740993 // true

看到这个结果,很多人第一反应是"JS 出 bug 了"。

其实没有,这是 JavaScript 数值模型决定的。


原理:为什么会精度丢失?

JavaScript 的 number 底层是 IEEE 754 双精度浮点数

它并不是"任意精度整数",只有 53 位有效精度(含隐藏位)。

所以 JS 能安全表示的最大整数是:

js 复制代码
Number.MAX_SAFE_INTEGER // 9007199254740991(2^53 - 1)

一旦超过这个范围,就会出现:

  • 相邻整数无法都精确表示(中间会跳号)
  • 不同整数可能映射到同一个可表示值

这就是"大整数看起来被改了"的根因。


关键点:精度丢失通常发生在 JSON 解析阶段

很多同学以为是运算时才丢精度,其实在前端接收响应时就可能已经丢了。

比如后端返回:

json 复制代码
{ "id": 9876543210123456789 }

如果你直接走原生 JSON.parse,这个值会被转成 JS number

而超出安全范围后,精度损失通常是不可逆的。


我在项目里的方案:请求层统一接入 json-bigint

我在 axiostransformResponse 里用了 json-bigint,并配置:

  • storeAsString: true

意思是:大整数不要转 number,直接按字符串保存,确保"值不变形"。

实际代码(简化版)

ts 复制代码
import axios from 'axios'
import JSONbig from 'json-bigint'

const JSONbigParser = JSONbig({ storeAsString: true })

const service = axios.create({
  transformResponse: [
    function (data) {
      if (!data) return data
      try {
        // 用 JSONbig 解析,超大数字按字符串保留
        return JSONbigParser.parse(data)
      } catch (err) {
        console.warn('JSON 解析失败,返回原始数据', err)
        return data
      }
    },
  ],
})

用了以后会发生什么变化?

后端:

json 复制代码
{ "companyId": 9876543210123456789 }

前端拿到:

json 复制代码
{ "companyId": "9876543210123456789" }

精度保住了,值可回传、可比对、可展示。

相关推荐
IT_陈寒4 分钟前
Redis持久化丢失数据的坑,这次终于被我填平了
前端·人工智能·后端
独泪了无痕1 小时前
Lodash-JavaScript的实用工具库
前端·javascript
有趣的老凌1 小时前
用 Vibe Coding 搭了一个完整小程序「一定能成」
前端·javascript·后端
kyriewen12 小时前
Anthropic 估值逼近万亿美元,Claude Sonnet 5 + Claude Science 一天两连发
前端·ai编程·claude
小徐_233313 小时前
Wot UI 2.2.0 发布:Button 新增 subtle,VideoPreview 预览体验继续增强
前端·微信小程序·uni-app
天蓝色的鱼鱼15 小时前
关于 CSS 你可能不知道的属性,但关键时刻很有用
前端·css
泯泷16 小时前
第 2 篇:设计第一套字节码:Opcode、Instruction 与 Constant Pool
前端·javascript·安全
妙码生花16 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(十五):优化细节、网络请求封装
前端·后端·ai编程
泯泷16 小时前
第 1 篇:从 1 + 2 开始:亲手写出第一台 JSVM
前端·javascript·安全