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

相关推荐
橙序员小站1 小时前
Agent Skill 是什么?一文讲透 Agent Skill 的设计与实现
前端·后端
炫饭第一名4 小时前
速通Canvas指北🦮——基础入门篇
前端·javascript·程序员
王晓枫4 小时前
flutter接入三方库运行报错:Error running pod install
前端·flutter
符方昊4 小时前
React 19 对比 React 16 新特性解析
前端·react.js
ssshooter4 小时前
又被 Safari 差异坑了:textContent 拿到的值居然没换行?
前端
曲折4 小时前
Cesium-气象要素PNG色斑图叠加
前端·cesium
Forever7_4 小时前
Electron 淘汰!新的桌面端框架 更强大、更轻量化
前端·vue.js
Angelial5 小时前
Vue3 嵌套路由 KeepAlive:动态缓存与反向配置方案
前端·vue.js
jiayu5 小时前
Angular学习笔记24:Angular 响应式表单 FormArray 与 FormGroup 相互嵌套
前端
jiayu5 小时前
Angular6学习笔记13:HTTP(3)
前端