先记住这个答案
10n 是字面量写法,在数字后面加 n,适合代码里写死的常量。BigInt(value) 是一个普通函数(不能加 new),用来在运行时把 Number、字符串或布尔值转成 BigInt。两者得到的值完全一样,10n === BigInt(10) 为 true。真正要注意的是 BigInt() 的参数:传小数会抛 RangeError,传不合法的字符串会抛 SyntaxError,传一个超出安全范围的 Number 不会报错,但得到的已经是错误的值。
- 常量写
10n,运行时数据用BigInt() - 大整数从字符串构造以免先丢精度
- 非整数不能直接转换成 BigInt
BigInt不能new,它不是构造函数
BigInt() 对不同输入的反应
先看各种输入的结果,重点看第二、三行的对比。
console.log(10n === BigInt(10), BigInt('10') === 10n)
console.log(String(BigInt(9007199254740993))) // 从 Number 转
console.log(String(BigInt('9007199254740993'))) // 从字符串转
console.log(String(BigInt('0x1f')), String(BigInt(' 12 ')))
for (const input of [10.1, '10.1', 'abc']) {
try { BigInt(input) } catch (e) { console.log(input, e.name) }
}
try { new BigInt(1) } catch (e) { console.log('new BigInt:', e.name) }查看输出与解释
true true
9007199254740992
9007199254740993
31 12
10.1 RangeError
10.1 SyntaxError
abc SyntaxError
new BigInt: TypeError9007199254740993 是 2^53 + 1,超出了 Number 能精确表示的整数范围。代码里写这个数字字面量时,引擎先把它解析成最接近的双精度浮点数,也就是 9007199254740992,然后才交给 BigInt()。所以 BigInt() 拿到的已经是错的,它没法还原。传字符串就不同,BigInt 直接按字符解析,每一位都保住了。
字符串解析时前后空白会被忽略,支持 0x、0o、0b 前缀,但不支持小数点、科学计数法,也不支持 n 后缀,BigInt('10n') 同样是 SyntaxError。
字面量的语法规则
字面量只能是整数:1.5n 是语法错误,1e3n 也是,代码根本跑不起来。进制前缀可以用,0x1fn 等于 31n,0b101n 等于 5n。以 0 开头的老式八进制写法 010n 不允许。数字分隔符可以用,1_000_000n 是合法的。
字面量的好处是没有转换这一步,不存在精度问题。所以代码里用到的大常量,一律写成字面量,不要写成 BigInt(一个很大的数字)。
容易答错的地方
- 以为
BigInt(Number.MAX_SAFE_INTEGER + 2)能得到正确结果 - 加法在
Number里就已经算错了,结果是9007199254740992而不是...993。要先转再算:BigInt(Number.MAX_SAFE_INTEGER) + 2n。 - 以为
new BigInt()能创建包装对象 BigInt和Symbol一样,不允许new,会抛TypeError。这是故意的,避免出现new Boolean(false)那种永远为真的包装对象。确实需要对象形式可以用Object(10n),但实际开发中几乎用不到。- 以为从接口拿到的数字再
BigInt()就安全了 JSON.parse把大整数解析成Number时精度已经丢了,之后再转BigInt无济于事。后端要把 64 位 ID 以字符串形式下发,前端用BigInt(str)转。
面试官还会怎么问?
怎么避免 BigInt 在后续代码里被意外转成 Number?
好在大部分意外转换会直接报错:和 Number 混合运算、一元 +、Math 方法都会抛 TypeError,这比悄悄丢精度好排查。真正要当心的是显式的 Number(b)、parseInt(String(b)) 和序列化环节。输出到接口和存储时统一用 String(b),读回来再 BigInt(str)。
BigInt 怎么转成字符串,带不带 n?
String(10n) 和 10n.toString() 都是 '10',没有 n。toString 还能传进制,255n.toString(16) 是 'ff'。只有在控制台直接打印时,显示上才会带 n。
怎么把 BigInt 限制在 64 位范围内?
用 BigInt.asIntN(64, x) 或 BigInt.asUintN(64, x),分别按有符号和无符号 64 位截断。和 BigInt64Array 或后端的 int64 对接时会用到。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。