先记住这个答案
BigInt 是一种新的原始类型,typeof 返回 'bigint',用来表示超出 Number 安全范围的整数,比如数据库的 64 位 ID。它和 Number 之间有几条硬限制:算术运算不能混用,1n + 1 会抛 TypeError;不能传给 Math.max、Math.round 这些方法;不支持一元 +;只能表示整数,除法会直接截掉小数。比较运算是例外,1n < 2、1n == 1 都可以正常工作。
- BigInt 与 Number 不能混合算术
- 比较运算可以混用,
1n == 1为true BigInt除法向零截断,没有小数- 一元加号和 JSON 默认不支持 BigInt
混合运算会发生什么
先看代码,每一条都是面试常问的点。
const a = 10n
console.log(typeof a)
try { a + 1 } catch (e) { console.log('a + 1:', e.name) }
try { Math.max(a, 1n) } catch (e) { console.log('Math.max:', e.name) }
console.log(String(a / 3n), String(-7n / 2n)) // 除法向零截断
console.log(1n == 1, 1n === 1, 2n > 1) // 比较可以跨类型
console.log(String(a + BigInt(1)), Number(a) + 1)
const big = 2n ** 64n
console.log(String(big), Number(big)) // 转回 Number 后精度不够查看输出与解释
bigint
a + 1: TypeError
Math.max: TypeError
3 -3
true false true
11 11
18446744073709551616 1844674407370955200010n / 3n 得到 3n,-7n / 2n 得到 -3n,是向零截断,不是向下取整。1n === 1 为 false,因为严格相等要求类型相同。最后一行 2n ** 64n 本身是精确的,转成 Number 后输出的末尾变成了一串 0,说明已经超出 Number 能逐位精确表示的范围。
为什么要设计成不能混用
Number 是 64 位浮点数,只能精确表示 -(2^53 - 1) 到 2^53 - 1 之间的整数,但它能表示小数。BigInt 能表示任意大的整数,但表示不了小数。两边各有对方装不下的值。
如果 1n + 1.5 自动转成 BigInt,小数部分就没了;自动转成 Number,大整数的精度就没了。无论选哪个方向,都有可能悄悄算错。所以语言选择直接报错,让开发者显式写 BigInt(x) 或 Number(y),自己为精度负责。
Math 上的方法都是为 Number 写的,同样不接受 BigInt。一元 + 在不少代码里被当成「转数字」的简写,如果 +1n 静默成功,会让 asm.js 这类依赖 +x 一定返回 Number 的代码出问题,所以它也被禁止了。
容易答错的地方
- 以为
BigInt能表示小数 BigInt只有整数。5n / 2n是2n,BigInt(1.5)直接抛RangeError。涉及金额这类需要小数的场景,通常是把单位换成「分」再用整数算,或者用专门的十进制库。- 以为
JSON.stringify能处理BigInt JSON.stringify({ id: 1n })会抛TypeError。常见做法是先转成字符串,或者给BigInt.prototype加toJSON。后端返回的大 ID 也应该用字符串传,前端JSON.parse拿到数字时精度已经丢了。- 以为
>>>也能用 - 位运算里
&、|、^、<<、>>都支持BigInt,唯独无符号右移>>>不支持,因为BigInt没有固定位宽,「无符号」没有意义。
面试官还会怎么问?
后端返回的 64 位 ID 前端怎么处理?
最稳的是让后端把 ID 序列化成字符串。如果改不了后端,要在 JSON.parse 之前处理,比如用支持大整数的 JSON 解析库,或者用 JSON.parse 的 reviver 第三个参数 context.source 拿到原始文本(较新的引擎才支持,需要确认目标环境)。
BigInt 在条件判断里怎么算真假?
和 Number 一样:0n 是假值,其他都是真值。if (0n) 不会进入分支,0n == false 为 true。
BigInt 的性能怎么样?
比 Number 慢,因为它是任意精度的,每次运算都可能要分配内存。普通计数、下标、坐标这类在安全范围内的计算不要用 BigInt,只在确实可能超过 2^53 的场景用。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。