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

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

相关推荐
PILIPALAPENG2 小时前
Python 语法速成指南:前端开发者视角(JS 类比版)
前端·人工智能·python
JYeontu2 小时前
轮播图不够惊艳?试下这个立体卡片轮播图
前端·javascript·css
张就是我1065922 小时前
从前端角度理解 CVE-2026-31431
前端
AGoodrMe2 小时前
swift基础之async/await
前端·ios
irving同学462382 小时前
从零搭建生产级 RAG:Embedding、Chunking、Hybrid Search 与 Reranker
前端·后端
卡卡军2 小时前
vue3-sketch-ruler v3 升级详解:从 Vue 组件到跨框架标尺引擎
前端
还有多久拿退休金2 小时前
让看不见的 AI 动手画画——我意外造出了一个"绘图 Agent"
前端
陆枫Larry2 小时前
一次 iOS 橡皮筋弹性滚动的排查:从 absolute 到 fixed
前端
灏仟亿前端技术团队2 小时前
拆解亿级 SaaS 平台:Shopify 前端技术生态与架构避坑指南
前端
亲亲小宝宝鸭2 小时前
如何监听DOM尺寸的变化?element-resize-detector 和 resizeObserver
前端·javascript