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

相关推荐
辻戋2 小时前
从零实现React Scheduler调度器
前端·react.js·前端框架
徐同保2 小时前
使用yarn@4.6.0装包,项目是react+vite搭建的,项目无法启动,报错:
前端·react.js·前端框架
Qrun3 小时前
Windows11安装nvm管理node多版本
前端·vscode·react.js·ajax·npm·html5
中国lanwp3 小时前
全局 npm config 与多环境配置
前端·npm·node.js
JELEE.4 小时前
Django登录注册完整代码(图片、邮箱验证、加密)
前端·javascript·后端·python·django·bootstrap·jquery
TeleostNaCl6 小时前
解决 Chrome 无法访问网页但无痕模式下可以访问该网页 的问题
前端·网络·chrome·windows·经验分享
前端大卫7 小时前
为什么 React 中的 key 不能用索引?
前端
你的人类朋友7 小时前
【Node】手动归还主线程控制权:解决 Node.js 阻塞的一个思路
前端·后端·node.js
小李小李不讲道理9 小时前
「Ant Design 组件库探索」五:Tabs组件
前端·react.js·ant design
毕设十刻9 小时前
基于Vue的学分预警系统98k51(程序 + 源码 + 数据库 + 调试部署 + 开发环境配置),配套论文文档字数达万字以上,文末可获取,系统界面展示置于文末
前端·数据库·vue.js