2020 年 9 月 21 日

BigInt

最近新增
這是最近新增到語言中的內容。你可以在 https://caniuse.dev.org.tw/#feat=bigint 找到目前支援的狀態。

BigInt 是一種特殊的數字類型,可支援任意長度的整數。

bigint 是透過在整數文字的結尾加上 n,或呼叫函式 BigInt(可從字串、數字等建立 bigint)建立的。

const bigint = 1234567890123456789012345678901234567890n;

const sameBigint = BigInt("1234567890123456789012345678901234567890");

const bigintFromNumber = BigInt(10); // same as 10n

數學運算子

BigInt 大多可以像一般數字一樣使用,例如

alert(1n + 2n); // 3

alert(5n / 2n); // 2

請注意:除法 5/2 會傳回無小數點、四捨五入至 0 的結果。所有 bigint 運算都會傳回 bigint。

我們無法混合 bigint 和一般數字

alert(1n + 2); // Error: Cannot mix BigInt and other types

如果需要,我們應該明確轉換它們:使用 BigInt()Number(),如下所示

let bigint = 1n;
let number = 2;

// number to bigint
alert(bigint + BigInt(number)); // 3

// bigint to number
alert(Number(bigint) + number); // 3

轉換運算永遠都是靜默的,絕不會產生錯誤,但如果 bigint 太大而無法符合數字類型,那麼額外的位元會被切斷,因此我們在執行此類轉換時應小心。

bigint 不支援單元加號

單元加號運算子 +value 是將 value 轉換為數字的眾所周知方法。

為了避免混淆,bigint 不支援此運算子

let bigint = 1n;

alert( +bigint ); // error

因此,我們應該使用 Number() 將 bigint 轉換為數字。

比較

比較,例如 <>,適用於 bigint 和數字

alert( 2n > 1n ); // true

alert( 2n > 1 ); // true

請注意,由於數字和 bigint 屬於不同的類型,因此它們可以相等 ==,但不能嚴格相等 ===

alert( 1 == 1n ); // true

alert( 1 === 1n ); // false

布林運算

if 或其他布林運算中,bigint 的行為就像數字。

例如,在 if 中,bigint 0n 為假值,其他值為真值

if (0n) {
  // never executes
}

布林運算子,例如 ||&& 等,也適用於 bigint,類似於數字

alert( 1n || 2 ); // 1 (1n is considered truthy)

alert( 0n || 2 ); // 2 (0n is considered falsy)

Polyfill

Polyfill bigint 很棘手。原因是許多 JavaScript 運算子,例如 +- 等,在 bigint 上的行為與一般數字不同。

例如,bigint 的除法總是傳回 bigint(必要時四捨五入)。

為了模擬這種行為,polyfill 需要分析程式碼並將所有此類運算子替換為其函式。但這樣做很麻煩,而且會耗費大量效能。

因此,沒有廣為人知的良好 polyfill。

儘管如此,JSBI 函式庫的開發人員提出了相反的方式。

此函式庫使用自己的方法實作大數字。我們可以使用它們來取代原生 bigint

運算 原生 BigInt JSBI
從數字建立 a = BigInt(789) a = JSBI.BigInt(789)
加法 c = a + b c = JSBI.add(a, b)
減法 c = a - b c = JSBI.subtract(a, b)

…然後使用多重填補(Babel 外掛程式)將 JSBI 呼叫轉換成原生大整數,適用於支援原生大整數的瀏覽器。

換句話說,這種方法建議我們使用 JSBI 撰寫程式碼,而不是原生大整數。但 JSBI 在內部使用數字作為大整數,並嚴格按照規範模擬大整數,因此程式碼將會「準備好大整數」。

我們可以使用這種「原樣」的 JSBI 程式碼,適用於不支援大整數的引擎,以及支援大整數的引擎,多重填補會將呼叫轉換成原生大整數。

參考資料

教學課程地圖

留言

留言前請先閱讀…
  • 如果您有改善建議,請 提交 GitHub 問題 或提出拉取請求,而不是留言。
  • 如果您無法理解文章中的內容,請詳細說明。
  • 若要插入幾行程式碼,請使用 <code> 標籤,若要插入多行程式碼,請將其包覆在 <pre> 標籤中,若要插入超過 10 行程式碼,請使用沙盒 (plnkrjsbincodepen…)