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

相关推荐
YGY Webgis糕手之路2 小时前
OpenLayers 综合案例-轨迹回放
前端·经验分享·笔记·vue·web
90后的晨仔3 小时前
🚨XSS 攻击全解:什么是跨站脚本攻击?前端如何防御?
前端·vue.js
Ares-Wang3 小时前
JavaScript》》JS》 Var、Let、Const 大总结
开发语言·前端·javascript
90后的晨仔3 小时前
Vue 模板语法完全指南:从插值表达式到动态指令,彻底搞懂 Vue 模板语言
前端·vue.js
德育处主任3 小时前
p5.js 正方形square的基础用法
前端·数据可视化·canvas
烛阴3 小时前
Mix - Bilinear Interpolation
前端·webgl
90后的晨仔3 小时前
Vue 3 应用实例详解:从 createApp 到 mount,你真正掌握了吗?
前端·vue.js
德育处主任3 小时前
p5.js 矩形rect绘制教程
前端·数据可视化·canvas
前端工作日常4 小时前
我学习到的babel插件移除Flow 类型注解效果
前端·babel·前端工程化
前端工作日常4 小时前
我学习到的 Babel 配置
前端·babel·前端工程化