面試官:聊聊 BigInt?
我們知道,現在 JavaScript 有 7 種基礎類型,null/undefined/number/string/boolean/bigint/symbol。其中 bigint 是 ES2020 中正式加入的,有個別的面試官喜歡深挖這個特性,那么我們來了解一下 BigInt 到底是什么?我們為什么需要 BigInt 吧?
BigInt 是什么?
概念
我們知道 JavaScript 中 Number 類型最大的數值為 2^53- 1,也就是 Number.MAX_SAFE_INTEGER。
BigInt 是一種內置對象,它提供了一種方法來表示大于 2^53 - 1 的整數。也就是說,BigInt 可以表示任意大的整數。
聲明
可以在一個整數字面量后面加上 n 或者調用函數 BigInt() 定義一個 BigInt。如下:
const theBiggestInt = 9007199254740991n;
const alsoHuge = BigInt(9007199254740991);
// ? 9007199254740991n
類型檢測
typeof 檢測 BigInt 對象返回 bigint 字符串。
typeof 1n === 'bigint'; // truetypeof BigInt('1') === 'bigint'; // true
BigInt 基礎語法和注意點
BigInt 很多時候表現跟 Number 類型很像,但也有很多不同的點,這些點在用到 BigInt 類型的時候,需要思考以下的點:
運算:
語法點 | 支持度 | 備注 |
+、*、-、**、% | 支持 | |
/ | 不支持 | 會進行向下取整 |
單目 (+) 運算符 | 不支持 | |
>>>(無符號右移) | 不支持 | 因為 BigInt 都是有符號的 |
位運算(除了無符號右移) | 支持 | |
Math 對象方法 | 不支持 |
說明:
- 除法的時候,當使用 BigInt 時,帶小數的運算會被取整
const expected = 4n / 2n;
// ? 2n
const rounded = 5n / 2n;
// ? 2n, not 2.5n
- 與 Number 混合運算的話。必須轉換成同一種類型,有時候會造成精度丟失的問題,所以不建議這么使用
- 在對象中使用 BigInt 的時候,假如使用 JSON.stringify() 會發生類型錯誤(TypeError)
綜上所述,可以看到 BigInt 的使用需要注意的點還是非常多的,并且在和 Number 類型轉換的時候還會發生精度丟失問題,因而建議僅在值可能大于2^53 時使用 BigInt 類型。
那么 BigInt 現在有哪些應用場景呢?
BigInt 的應用場景
高精度時間戳
大于 2^53 - 1 的整數的一個應用場景就是高精度時間戳。精確到納秒級別的時間戳很常見,經常用來記錄特定程序的執行事件,以便進行性能分析,BigInt 可以表示高精度時間戳,在后端性能分析、性能調優中發揮作用。
大整數 ID
比如 Twitter 的 id 生成服務,當 id 持續增長時,就會超出 JS 的安全范圍,因此要求同時冗余地返回字符串型的 id。假如有 BigInt 類型就可以直接使用。
兼容性 & PolyFill
can i use[1] 中的數據顯示,Chrome 的支持度會好很多,IE 全軍覆沒,整體覆蓋 92.25% 的用戶。
現在可以使用 JSBI — pure-JavaScript BigInts[2] 這個庫來實現 BigInt。JSBI 是直接使用了 V8 和 Chrome 中 BigInt 的設計和實現方式,功能與瀏覽器中一致,語法稍有不同。假如 BigInt 被所有的瀏覽器原生支持后,可以使用 babel 插件 babel-plugin-transform-jsbi-to-bigint[3] 移除 JSBI 轉為原生的 BigInt 語法。
總結
總體而言,BigInt 可以表示任意大的整數,目前的使用場景是相對較少的。BigInt 的使用需要注意的點還是非常多的,因而建議僅在值可能大于2^53 時使用 BigInt 類型。目前的兼容性一般,可以考慮使用 jsbi 這個庫替代。
參考
JSBI — pure-JavaScript BigInts[4]
BigInt-MDN[5]
參考資料
[1]can i use: https://caniuse.com/?search=bigint
[2]JSBI — pure-JavaScript BigInts: https://github.com/GoogleChromeLabs/jsbi
[3]babel-plugin-transform-jsbi-to-bigint: https://github.com/GoogleChromeLabs/babel-plugin-transform-jsbi-to-bigint
[4]JSBI — pure-JavaScript BigInts: https://github.com/GoogleChromeLabs/jsbi
[5]BigInt-MDN: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/BigInt