前端大整数精度丢失:一次踩坑后的实战解决方案(`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" }

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

相关推荐
一位正在转型AI全栈的前端工程师1 小时前
AI 全栈学习之旅 -Week 11:从 CLI 到浏览器:用 FastAPI、SSE 和 Vue 3 做一个可审核的 ReAct Agent
前端·python
10share1 小时前
我为什么用 React 重写了一个 VitePress
前端·react.js
计算机魔术师1 小时前
GPT-6 Astra 发布后,Sebastian Raschka 解析 looped transformer 与隐藏推理链传闻
前端
不可能片场1 小时前
Electron 退化成 node:一个环境变量的锅
前端·electron
楚楚河河1 小时前
js 变量声明
前端
Cicada1281 小时前
Web 服务器怎么选
运维·服务器·前端
不可能片场1 小时前
接口返回 200 不代表活着:catch-all 路由的陷阱
前端·electron
用户921080262861 小时前
Cookie 和 Token,到底谁在负责登录态
前端
阳火锅2 小时前
2025,记住这一年!它是古法编程的最后一年。
前端·javascript·面试
sibylyue2 小时前
【报表和BI大屏】ECharts数据可视化大屏 / 驾驶舱
前端·信息可视化·echarts