深入理解 JavaScript 和 TypeScript 中的 `BigInt` 类型及其 Polyfill 方法

在现代 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 的环境中,直接使用 123nBigInt("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 或使用第三方库模拟其行为。

方法一:使用第三方大整数库

最常见的选择是:

✅ 使用 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.addJSBI.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,推荐封装一层兼容接口,并为关键计算路径提供替代实现以保障兼容性。

相关推荐
鱼樱前端9 分钟前
重度Cursor用户 最强 Cursor Rules 和 Cursor 配置 mcp 以及最佳实践配置方式
前端
曼陀罗10 分钟前
Path<T> 、 keyof T 什么情况下用合适
前端
锈儿海老师15 分钟前
AST 工具大PK!Biome 的 GritQL 插件 vs. ast-grep,谁是你的菜?
前端·javascript·eslint
飞龙AI17 分钟前
鸿蒙Next实现瀑布流布局
前端
快起来别睡了19 分钟前
代理模式:送花风波
前端·javascript·架构
海底火旺21 分钟前
电影应用开发:从代码细节到用户体验优化
前端·css·html
陈随易30 分钟前
Gitea v1.24.0发布,自建github神器
前端·后端·程序员
前端付豪32 分钟前
汇丰银行技术架构揭秘:全球交易稳定背后的“微服务+容灾+零信任安全体系”
前端·后端·架构
邹荣乐35 分钟前
uni-app开发微信小程序的报错[渲染层错误]排查及解决
前端·微信小程序·uni-app
今天出摊吗35 分钟前
表单元素的默认提交行为
前端