ECMAScript 2020:BigInt 的使用方法和应用场景探究

什么是 BigInt?

BigInt 是 ECMAScript 2020 中新增的一种数据类型,它用于表示超过 JavaScript 数值类型(Number) 最大安全整数限制的数字。在 JavaScript 中,Number 类型最大的安全整数是 2 的 53 次方减 1,也就是:9007199254740991。如果你需要处理更大的整数,可以使用 BigInt 类型。

BigInt 类型是通过在数字末尾添加 n 或者使用 BigInt() 方法来创建的。如下所示:

const bigIntNum = 9007199254740992n;
const anotherBigIntNum = BigInt("9007199254740993");

BigInt 的使用方法

基本运算

BigInt 运算支持大多数 JavaScript 数值运算符,包括加、减、乘、除、求余、指数运算等,例如:

const bigIntNum1 = 987654321n;
const bigIntNum2 = 123456789n;

const addResult = bigIntNum1 + bigIntNum2; // 1111111110n
const subtractResult = bigIntNum1 - bigIntNum2; // 864197532n
const multiplyResult = bigIntNum1 * bigIntNum2; // 121932631112635269n
const divideResult = bigIntNum1 / bigIntNum2; // 7n
const moduloResult = bigIntNum1 % bigIntNum2; // 36909816n
const exponentiationResult = bigIntNum1 ** 3n; // 9697399250598743077301681n

转换操作

可以使用 Number() 和 BigInt() 函数互相转换 Number 和 BigInt 类型:

const bigIntNum = 9007199254740992n;
const numberNum = Number(bigIntNum); // 9007199254740992
const newBigIntNum = BigInt(numberNum); // 9007199254740992n

需要注意的是,BigInt 类型不能与 Number 类型一起参与一些运算,需要进行类型转换。

const bigIntNum = 9007199254740992n;
const numberNum = 100;

const addResult = bigIntNum + BigInt(numberNum); // 9007199254741092n

比较运算

与 JavaScript 原生的比较运算符(==、!=、<、>、<=、>=)不同,BigInt 类型使用 === 和 !== 运算符进行比较。注意,使用 BigInt 与常规数值类型进行比较和计算时,常规数值类型会自动转换为 BigInt 类型,但浮点数将被舍弃并转为整数。

const bigIntNum = 12345n;

console.log(bigIntNum === 12345); // false
console.log(bigIntNum == 12345); // true
console.log(bigIntNum === BigInt(12345)); // true
console.log(bigIntNum === BigInt(12345.6)); // true

BigInt 的应用场景

在程序中有许多需要处理超过 JavaScript 数值类型表示范围的情况,例如时间戳、加密哈希值等。BigInt 类型可以涵盖这些场景。以下是一些例子:

处理大数的加密算法

处理数据时,可能需要使用加密算法。加密算法需要进行大量的数学计算,如果处理的数据量很大,就会超出 JavaScript 的数值范围,这时就可以使用 BigInt 类型。

// 计算 HMAC-SHA256
async function hmacSHA256(key, data) {
  // 将 key 和 data 转化成需要的格式
  const keyInBits = new TextEncoder().encode(key);
  const dataInBits = new TextEncoder().encode(data);

  // 导出循环运行 HMAC-SHA256
  const keyMaterial = await crypto.subtle.importKey(
    "raw",
    keyInBits,
    { name: "HMAC", hash: "SHA-256" },
    false,
    ["sign"]
  );
  const result = await crypto.subtle.sign(
    "HMAC",
    keyMaterial,
    dataInBits.buffer
  );

  // 将结果转化成需要的数字格式
  const bigIntResult = convertBufferToInt(BigInt.prototype, new Uint8Array(result));
  return bigIntResult;
}

function convertBufferToInt(intClass, byteArray) {
  const bytelen = byteArray.byteLength;
  let result = new intClass(0);
  for (let i = 0; i < bytelen; i++) {
    result = result * 256n + BigInt(byteArray[i]);
  }
  return result;
}

(async () => {
  const digest = await hmacSHA256("a secret key", "some data");
  console.log("HMAC-SHA256 digest in BigInt format:", digest);
})();

处理时间戳

在 JavaScript 中,Date 类型表示的时间戳的最大时间范围是 1970 年至 2038 年。如果需要处理更早或更晚的时间戳,就需要使用 BigInt 类型。

const timestamp = 1623916628000n;
const bigIntDate = new Date(Number(timestamp));
console.log(bigIntDate); // Sat Jun 19 2021 17:43:48 GMT+0800 (China Standard Time)

总结

BigInt 类型作为 ECMAScript 2020 中的新功能,可以帮助我们轻松处理超过 JavaScript 数值类型表示范围的数字,广泛应用于 Web 应用的安全、金融和科学计算等领域。还需要注意的是,在使用 BigInt 类型时应注意类型转换,来使其与常规数值类型进行操纵和比较。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65b0be36add4f0e0ffa17743