number.max_safe_integer 为 9007199254740991,超限整数需用字符串或 bigint 处理,关键场景如 id、计数、加密、前后端一致性必须校验并规避精度丢失。

JavaScript 中 Number.MAX_SAFE_INTEGER 是 9007199254740991(即 2⁵³ − 1),超出这个范围的整数无法被精确表示,会导致精度丢失。算法设计时若涉及大整数运算、ID 处理、时间戳、哈希计算或金融类累加,必须主动规避该限制,不能依赖运行时自动修复。
识别哪些场景真正需要安全整数
不是所有大数都危险:浮点近似可接受的场景(如 Canvas 坐标、动画进度)无需强校验;但以下情况必须检查:
- 数据库主键(尤其是 Snowflake ID 或自增 long 类型 ID)
- 精确计数(用户积分、库存数量、分页 offset/limit 超过千万级)
- 加密相关计算(如模幂、哈希种子、序列号生成)
- 前后端整数一致性校验(后端返回
12345678901234567890,前端JSON.parse后变成12345678901234567000)
用字符串代替数字处理超限整数
当整数可能超过 MAX_SAFE_INTEGER 且需保持精度时,应全程以字符串形式传递和操作,避免转为 Number:
- API 返回大整数字段时,后端加引号(
"id": "12345678901234567890"),前端不parseInt或+转换 - 比较大小用字符串字典序(仅适用于无前导零、正整数):
a.length > b.length || (a.length === b.length && a > b) - 加减乘除可用 big.js、bignumber.js 等库,而非原生
+/-
用 BigInt 替代 Number 进行整数运算
BigInt 是 ES2020 引入的原生类型,支持任意精度整数,但有使用约束:
- 字面量需加
n后缀:12345678901234567890123n;构造需传字符串:BigInt("12345678901234567890123") - 不能与
Number混合运算(1n + 2报错),需显式转换(注意BigInt(2.5)会截断小数) - JSON 不支持
BigInt,序列化前需转字符串:JSON.stringify(obj, (k, v) => typeof v === 'bigint' ? v.toString() : v) - 部分老环境(如 IE、Node.js
设计阶段就规避整数溢出风险
比起事后修补,更高效的是从接口和数据流源头控制:
- ID 字段统一约定为字符串类型(Swagger/OpenAPI 标注
type: string,而非integer) - 分页参数
offset超过1e7时强制改用游标(cursor)模式,避免大整数累加 - 服务端生成时间戳用毫秒字符串(
Date.now().toString())或process.hrtime()配合序列号,不拼接成超长数字 - 在关键入口添加运行时检测:
if (Number.isSafeInteger(n)) { /* safe path */ } else { /* fallback to string/bigint */ }
不复杂但容易忽略:一次隐式转换(比如 obj.id * 1)、一个未加引号的 JSON 字段、一个没校验的 parseInt,都可能让整个链路精度崩塌。把“是否安全”当作接口契约的一部分,比修复 bug 更省力。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











