在现代 JavaScript 和 TypeScript 中,BigInt
类型为开发者提供了对任意精度整数 的原生支持,解决了传统 Number
类型在处理超大整数时精度丢失的问题。本文将系统介绍 BigInt
的使用方式、注意事项,以及在不支持 BigInt
的旧环境(如老版本浏览器或引擎)中如何进行 polyfill。
一、背景:JavaScript 中的数字限制
在 ECMAScript 中,Number
类型遵循 IEEE 754 双精度浮点数标准。这种表示方式能安全表示的整数范围是:
js
Number.MIN_SAFE_INTEGER === -9007199254740991
Number.MAX_SAFE_INTEGER === 9007199254740991
超过这个范围时,整数的表示将不再精确。例如:
js
9999999999999999 === 10000000000000000 // true,不正确
二、BigInt
类型简介
BigInt
是一种新引入的原生数据类型,用于表示任意长度的整数。通过在整数后加 n
,或调用 BigInt()
构造函数创建。
✅ 示例:
js
const a = 1234567890123456789012345678901234567890n;
const b = BigInt("9007199254740993");
console.log(a * b); // 任意精度乘法
✅ 类型识别:
js
typeof 123n === "bigint"; // true
三、BigInt
的限制与注意事项
❌ 与 Number
不能混合运算
js
1n + 1; // ❌ TypeError: Cannot mix BigInt and other types
需要显式转换:
js
BigInt(1) + 1n // ✅ OK
❌ 不支持部分标准库 API
如 JSON 不支持 BigInt
:
js
JSON.stringify(123n); // ❌ TypeError
你需要手动转成字符串或使用自定义 replacer:
js
JSON.stringify({ big: 123n }, (_, v) =>
typeof v === 'bigint' ? v.toString() : v
);
📛 浏览器兼容性限制
BigInt
是在 ECMAScript 2020(ES11) 中引入的,以下是主流浏览器的最低支持版本:
浏览器 | 支持版本 |
---|---|
Chrome | 67+ |
Firefox | 68+ |
Safari | 14+ |
Edge (Chromium) | 79+ |
Node.js | 10.4.0+(需启用标志) 12.0.0+(默认支持) |
Internet Explorer | ❌ 不支持 |
💡 说明:
- 在不支持
BigInt
的环境中,直接使用123n
或BigInt("123")
会抛出ReferenceError
。 - 为确保代码健壮性,应使用
typeof BigInt === 'function'
进行兼容性检查。
✅ 示例:检查运行环境是否支持 BigInt
js
if (typeof BigInt === 'function') {
const big = BigInt("12345678901234567890");
console.log(big);
} else {
console.warn("BigInt is not supported in this environment.");
}
四、TypeScript 中的 BigInt
在 TypeScript 中,需要启用编译选项:
json
{
"compilerOptions": {
"target": "ES2020" // 或 ESNext
}
}
可以声明类型为:
ts
let big: bigint = 100n;
五、在不支持 BigInt
的环境中如何进行 Polyfill?
原生 BigInt
可能不被某些旧浏览器(如 Internet Explorer)支持。在这种环境中,可以通过引入 Polyfill 或使用第三方库模拟其行为。
方法一:使用第三方大整数库
最常见的选择是:
- big-integer
- decimal.js
- jsbi(官方推荐模拟 BigInt 的行为)
✅ 使用 jsbi
示例:
bash
npm install jsbi
js
import JSBI from 'jsbi';
const a = JSBI.BigInt("9007199254740993");
const b = JSBI.BigInt("10");
const c = JSBI.multiply(a, b);
console.log(JSBI.toNumber(c)); // 输出结果
你需要用 JSBI.add
、JSBI.multiply
等函数来代替原生运算符。
方法二:简单封装 Polyfill 接口
你可以封装一套兼容接口:
ts
const BigIntCompat = typeof BigInt !== 'undefined'
? BigInt
: (val: any) => JSBI.BigInt(val);
const Add = (a: any, b: any) =>
typeof BigInt !== 'undefined' ? a + b : JSBI.add(a, b);
// 使用:
const a = BigIntCompat("100000000000000000000");
const b = BigIntCompat("2");
const c = Add(a, b);
console.log(c.toString ? c.toString() : c); // 字符串化输出
六、总结
特性 | Number |
BigInt |
---|---|---|
精度限制 | ±2^53 - 1 | 无 |
支持小数 | ✅ | ❌ |
支持 JSON 序列化 | ✅ | ❌(需转换) |
运算符支持 | ✅ | ✅(但不能混用) |
兼容性 | 广泛 | ES2020+ |
✨ 开发建议
- 对于需要超大整数(如金融、密码学、ID 编码)的应用,推荐使用
BigInt
。 - 若需兼容旧环境,可借助
jsbi
等库进行 polyfill。 - 在 TypeScript 项目中使用
bigint
类型时注意配置编译目标。
如需在真实项目中平滑支持 BigInt
,推荐封装一层兼容接口,并为关键计算路径提供替代实现以保障兼容性。