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

相关推荐
贵沫末8 分钟前
React——基础
前端·react.js·前端框架
aklry20 分钟前
uniapp三步完成一维码的生成
前端·vue.js
Rubin9327 分钟前
判断元素在可视区域?用于滚动加载,数据埋点等
前端
爱学习的茄子27 分钟前
AI驱动的单词学习应用:从图片识别到语音合成的完整实现
前端·深度学习·react.js
用户38022585982428 分钟前
使用three.js实现3D地球
前端·three.js
程序无bug30 分钟前
Spring 面向切面编程AOP 详细讲解
java·前端
zhanshuo30 分钟前
鸿蒙UI开发全解:JS与Java双引擎实战指南
前端·javascript·harmonyos
撰卢1 小时前
如何提高网站加载速度速度
前端·javascript·css·html
10年前端老司机1 小时前
在React项目中如何封装一个可扩展,复用性强的组件
前端·javascript·react.js
Struggler2811 小时前
解决setTimeout/setInterval计时不准确问题的方案
前端