news 2026/2/13 5:14:23

BigInt 与 Number 的爱恨情仇,为何大佬都劝你“能用 Number 就别用 BigInt”?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
BigInt 与 Number 的爱恨情仇,为何大佬都劝你“能用 Number 就别用 BigInt”?

最近在写业务逻辑时,遇到一个非常诡异的 Bug。

数据库里的 User ID 是101092432494557966,但是前端请求回来的数据里,ID 竟然变成了101092432494557970

尾数的66变成了70,导致前端拿这个 ID 去查详情时,直接报 404 Not Found。

这简直是“灵异事件”。查了一圈代码,发现罪魁祸首竟然是JavaScript 的 Number 类型

// 模拟案发现场 const dbId = 101092432494557966n; // BigInt 从数据库出来 const apiResponse = Number(dbId); // 手贱转成了 Number console.log(apiResponse); // 输出: 101092432494557970 😱

为什么会这样?这就引出了今天的主角:BigIntNumber


🔍 原理剖析:Number 的“安全区”

JavaScript 的Number类型本质上是IEEE 754 双精度浮点数

它不是无限精度的,它只有53 个二进制位用来存储有效数字(尾数)。

1. 安全整数范围

JS 能“精准”表示的最大整数是Number.MAX_SAFE_INTEGER,即 $2^{53} - 1$。

数值为:9,007,199,254,740,991(约 9 千万亿)。

2. 精度丢失的真相

一旦数字超过这个安全范围(比如上面的 18 位 ID),Number 的“刻度尺”就不够用了。它无法分辨...966...970之间的微小差别,只能进行“四舍五入”,强制对齐到最近的一个可表示数值。

这就是为什么你的 ID 会变异。


⚔️ BigInt 的救赎与“三宗罪”

为了解决这个问题,ES2020 推出了BigInt。它可以表示任意大的整数。

看起来很美好对吧?数据库里的bigint字段直接映射成 JS 的BigInt好像很完美。

但是,在实际工程中,BigInt 其实是个“刺头”。很多资深开发者的原则是:除非迫不得已,尽量用 Number。

为什么?因为 BigInt 有三大“工程痛点”:

痛点一:JSON 序列化炸弹(最致命)

这是 Node.js/NestJS 开发中最容易踩的坑。

JSON.stringify不支持 BigInt!

const user = { id: 100n, name: "John" }; JSON.stringify(user); // ❌ 报错: TypeError: Do not know how to serialize a BigInt

如果你的接口直接返回了包含 BigInt 的对象,整个请求会直接 500 挂掉。你必须手动处理每一个字段,或者配置全局拦截器,非常麻烦。

痛点二:生态隔离

JavaScript 生态中 99% 的第三方库(Lodash, Chart.js, Mathjs, Excel 导出库等)都是基于Number设计的。

如果你传一个BigInt进去,它们大概率会报错,或者计算出奇怪的结果。为了兼容,你不得不转来转去,代码写得像通心粉。

痛点三:严苛的类型运算

JS 不允许 BigInt 和 Number 混合运算,必须显式转换。

const money = 100n; const tax = 0.1; // ❌ 报错: Cannot mix BigInt and other types const total = money + tax;

这在业务逻辑复杂的代码中,会增加大量的心智负担。


💡 最佳实践:怎么选?怎么存?怎么传?

既然 Number 有精度上限,BigInt 又难用,我们在项目中到底该怎么办?

以下是经过实战验证的“黄金法则”

1. 什么时候必须用 BigInt?

只有满足以下条件时,才引入 BigInt:

  • 分布式 ID (Snowflake):如 Twitter 雪花算法生成的 ID(18-19 位),必超 Number 安全范围。

  • 高精度时间戳:纳秒级计时。

  • 加密货币/金融:涉及比特币等超大数值计算。

2. 什么时候坚决用 Number?

  • 金额(分):只要业务不超过9 千万亿(相信我,你公司的业务很难超过这个数),存“分”用 Number 绰绰有余。

  • 普通自增 ID:MySQL 的自增主键。

  • 数量、库存、点赞数

理由:享受原生 JSON 支持,享受极致的 CPU 浮点运算速度,兼容所有第三方库。

3. 工程化解决方案(核心)

针对“ID 精度丢失”和“JSON 报错”问题,标准的解决链路如下:

  • 数据库层:必须用BIGINTVARCHAR存储,确保源头不丢。

  • 后端计算层

    • 如果是 ID:用BigIntString传递。

    • 如果是金额:用Number计算(在安全范围内)。

  • 接口返回层(DTO)—— 关键一步!

千万不要把 BigInt 直接丢给前端!

千万不要把 BigInt 转成 Number 丢给前端!

正确做法:在返回给前端的那一刻,把大数 ID 转成 String

// NestJS DTO 示例 import { Transform } from 'class-transformer'; export class UserDto { // 1. 数据库里是 BigInt // 2. 这里的 Transform 负责在序列化给前端时,转成 String @Transform(({ value }) => String(value)) unionId: string; // 金额如果没超限,直接用 Number balance: number; }

前端 JavaScript 处理大数 ID 的唯一标准方案就是:把它当字符串处理


📝 总结

  1. 精度陷阱:超过 16 位的数字用Number存一定会丢精度,ID 会变异。

  2. 序列化坑BigInt无法被 JSON 序列化,会导致接口报错。

  3. 选型原则

    • 能用 Number 就用 Number(金额、计数、普通 ID)。

    • 超长 ID 必须用 BigInt/String

  4. 传输原则:后端计算可以用 BigInt,但给前端的数据,必须是 String

以后再看到后端传回来的 ID 尾数不对,别犹豫,直接去检查是不是中间某一步被偷偷转成Number了!


觉得有用的话,点赞收藏防踩坑!👍

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/13 20:32:34

Python计算机毕设之基于协同过滤算法的金融理财产品推荐系统python基于协同过滤算法的理财产品推荐系统(完整前后端代码+说明文档+LW,调试定制等)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

作者头像 李华
网站建设 2026/2/12 21:35:03

【课程设计/毕业设计】基于python的协同过滤的理财套餐推荐系统设计与实现python基于协同过滤算法的理财产品推荐系统【附源码、数据库、万字文档】

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

作者头像 李华
网站建设 2026/2/12 6:39:20

java+vue基于springboot的基于Web的小游戏集成网站_4spg9o8y

目录基于SpringBoot和Vue的Web小游戏集成网站技术栈功能模块部署与扩展适用场景开发技术源码文档获取/同行可拿货,招校园代理 :文章底部获取博主联系方式!基于SpringBoot和Vue的Web小游戏集成网站 该项目是一个结合Java后端框架SpringBoot和前端框架Vue…

作者头像 李华
网站建设 2026/2/14 0:01:36

【毕业设计】基于Spring Boot技术的公司日常考勤系统

💟博主:程序员陈辰:CSDN作者、博客专家、全栈领域优质创作者 💟专注于计算机毕业设计,大数据、深度学习、Java、小程序、python、安卓等技术领域 📲文章末尾获取源码数据库 🌈还有大家在毕设选题…

作者头像 李华
网站建设 2026/2/11 10:40:37

专注时钟:在线番茄工作法工具,重塑高效工作流

在数字时代,保持高度专注已成为稀缺而珍贵的“超能力”。面对无处不在的干扰,如何有效管理时间、提升工作效率?我们为您介绍一款基于经典番茄工作法设计的在线工具——专注时钟,帮助您在浏览器中轻松实现高效、可持续的工作节奏。…

作者头像 李华