在前端开发中,我们常常需要处理大量数值。在传统的 JavaScript 中,数值类型只能表现最大为 Number.MAX_SAFE_INTEGER
(2^53-1)的整数值,而 ES10 中新增加的 BigInt
类型则可以处理任意大的整数值,大大提高了前端开发的精度和灵活性。
在本文中,我们将介绍 BigInt
类型的基本用法、注意事项和一些实用技巧,以及如何在项目中充分利用 BigInt
类型的优势。
一、BigInt
类型的基本用法
1.1 基础语法
BigInt
类型的语法很简单,只需要在整数后面加上一个 n
即可。例如:
const number = 123456789012345678901n;
需要注意的是,不能在 BigInt
值前使用 0b
、0o
或0x
(二进制、八进制或十六进制等进制数值开头的标识),因为 BigInt
是用十进制表示的。
1.2 基本运算
大多数算术运算符和方法都能与 BigInt
类型一起使用,如 +
、-
、*
、/
、%
、**
、++
、--
、Math.abs()
等。不过需要注意,满足下列两个条件时,BigInt
才能与其他类型进行运算:
- 两个运算数必须都是
BigInt
类型; - 对于除法运算
/
,结果必须是整数值(向下取整)。
const a = 123456789012345678901n; const b = 98765432109876543210n; // 加减乘除 console.log(a + b); // 222222221122222222111n console.log(a - b); // 24791356702469135791n console.log(a * b); // 121932632275404633313965074342618703010n console.log(a / b); // 1n // 求余数与指数 console.log(a % b); // 1234567901234567901n console.log(a ** 2n); // 152415787532388367504953515625361987875019051084662812499420218813121n
1.3 转换为 BigInt
类型
BigInt()
可以将一个普通的数值或字符串转换为 BigInt
类型。需要注意的是,这个函数只能用于在 Number
或 String
能够表达的范围内。
console.log(BigInt(123)); // 123n console.log(BigInt("123456789012345678901")); // 123456789012345678901n
1.4 与 Number
类型转换
在 BigInt
类型和 Number
类型之间转换时需要注意,如果 BigInt
大于或等于 Number.MAX_SAFE_INTEGER
,则会发生截断。
const a = 12345678901234567890n; console.log(Number(a)); // 12345678901234567890 console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991 console.log(BigInt(Number.MAX_SAFE_INTEGER)); // 9007199254740991n console.log(BigInt(Number.MAX_SAFE_INTEGER + 1)); // 9007199254740992n
1.5 使用位运算符
BigInt
类型可以和 Number
类型一起使用,但是不支持位运算符。不过,ES10 中新增了三个用于 BigInt
类型的位运算符:&n
、|n
和 ^n
。例如:
const a = 12345678901234567890n; const b = 56789012345678901234n; console.log(a & b); // 475092313240332738 console.log(a | b); // 67134772522955157006n console.log(a ^ b); // 67134772522955157006n
二、注意事项
虽然 BigInt
类型可以处理任意大的整数值,但是在使用时需要注意下列几点:
2.1 不支持隐式转换
Number
类型可以随时隐式转换为 String
类型,也可以作为数组索引等随意转换为 String
类型,但是 BigInt
类型不支持隐式转换,需要显式调用 toString()
方法。例如:
const a = 12345678901234567890n; // 错误的写法 console.log("value is" + a); // TypeError: Cannot convert a BigInt value to a string // 正确的写法 console.log("value is" + a.toString()); // value is 12345678901234567890
2.2 与普通对象互操作
尽管 BigInt
是一种类型安全的数值类型,但是不能直接与普通对象进行互操作:
const a = 12345678901234567890n; // 错误写法 console.log(a + {}); // TypeError: Cannot convert object to primitive value // 正确写法 console.log(a + BigInt(Object.prototype.valueOf.call({}))); // 12345678901234567890n
2.3 与 JSON
互操作
在 JavaScript 中,JSON.parse()
和 JSON.stringify()
是两个非常常用的处理 JSON
数据的方法。但是由于 JSON
规范并不支持 BigInt
类型,因此 BigInt
类型和 JSON
一起使用时需要特别注意。
具体做法是自定义 JSON
序列化和反序列化方法,例如:
const a = { number: 123456789012345678901n }; const string = JSON.stringify(a, function(key, value) { return typeof value === "bigint" ? value.toString() : value; }); const parsed = JSON.parse(string, function(key, value) { return typeof value === "string" && /^\d+n$/.test(value) ? BigInt(value.slice(0, -1)) : value; }); console.log(parsed.number); // 123456789012345678901n
三、实用技巧
下面我们介绍几个实用技巧,帮助读者充分利用 BigInt
类型的优势。
3.1 处理高精度计算
在普通 JavaScript 中,大多数高精度计算的解决方案都需要用到字符串,或者使用第三方库,比如 big.js
。而有了 BigInt
类型之后,我们就可以不依赖于字符串和第三方库来处理高精度计算。
例如,求出斐波那契数列的第 n
项,可以使用递归和循环两种方法:
// 递归 function fibonacciRecursive(n) { if (n === 0n) return 0n; if (n === 1n) return 1n; return fibonacciRecursive(n - 1n) + fibonacciRecursive(n - 2n); } console.log(fibonacciRecursive(100n)); // 354224848179261915075n // 迭代 function fibonacciLoop(n) { let [a, b] = [0n, 1n]; while (n--) { [a, b] = [b, a + b]; } return a; } console.log(fibonacciLoop(100n)); // 354224848179261915075n
可以看到,在 BigInt
类型的支持下,递归和循环两种方法都可以在瞬间完成计算。
3.2 解决位运算问题
在普通 JavaScript 中,由于只支持 32 位的位运算符,很难解决一些和位运算有关的问题。比如,要求数组中所有数字的异或结果,可以使用 reduce()
和位运算符 ^
进行求解:
const nums = [1, 2, 3, 4, 5, 4, 3, 2, 1]; const result = nums .map(num => BigInt(num)) .reduce((acc, cur) => acc ^ cur, 0n) console.log(result); // 0n
3.3 解决类型检测问题
在普通 JavaScript 中,要判断一个值是否为整数有很多种方法,比如使用 Number.isFinite()
或 Math.floor()
。不过,有了 BigInt
类型之后,我们可以直接使用 typeof
进行类型检测。
function isInt(value) { return typeof value === "bigint"; } console.log(isInt(123456789012345678901n)); // true console.log(isInt(123456789012345678901)); // false
四、总结
ES10 中的 BigInt
类型带来了前所未有的精度和灵活性,使得前端开发可以更加自由地处理数据。虽然在使用时需要特别注意隐式转换和与普通对象的互操作,但是只要掌握了基本用法和一些实用技巧,就可以轻松解决高精度问题、位运算问题和类型检测问题,提高代码的可读性和可维护性。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65ab5cb4add4f0e0ff500285