Javascript BigInt

2023-02-17 10:53 更新

最近新增的特性

這是一個(gè)最近添加到 JavaScript 的特性。 你能在 https://caniuse.com/#feat=bigint 找到當(dāng)前支持狀態(tài)。

BigInt 是一種特殊的數(shù)字類(lèi)型,它提供了對(duì)任意長(zhǎng)度整數(shù)的支持。

創(chuàng)建 bigint 的方式有兩種:在一個(gè)整數(shù)字面量后面加 n 或者調(diào)用 BigInt 函數(shù),該函數(shù)從字符串、數(shù)字等中生成 bigint。

const bigint = 1234567890123456789012345678901234567890n;

const sameBigint = BigInt("1234567890123456789012345678901234567890");

const bigintFromNumber = BigInt(10); // 與 10n 相同

數(shù)學(xué)運(yùn)算符

?BigInt? 大多數(shù)情況下可以像常規(guī)數(shù)字類(lèi)型一樣使用,例如:

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

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

請(qǐng)注意:除法 5/2 的結(jié)果向零進(jìn)行舍入,舍入后得到的結(jié)果沒(méi)有了小數(shù)部分。對(duì) bigint 的所有操作,返回的結(jié)果也是 bigint。

我們不可以把 bigint 和常規(guī)數(shù)字類(lèi)型混合使用:

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

如果有需要,我們應(yīng)該顯式地轉(zhuǎn)換它們:使用 BigInt() 或者 Number(),像這樣:

let bigint = 1n;
let number = 2;

// 將 number 轉(zhuǎn)換為 bigint
alert(bigint + BigInt(number)); // 3

// 將 bigint 轉(zhuǎn)換為 number
alert(Number(bigint) + number); // 3

轉(zhuǎn)換操作始終是靜默的,絕不會(huì)報(bào)錯(cuò),但是如果 bigint 太大而數(shù)字類(lèi)型無(wú)法容納,則會(huì)截?cái)喽嘤嗟奈?,因此我們?yīng)該謹(jǐn)慎進(jìn)行此類(lèi)轉(zhuǎn)換。

BigInt 不支持一元加法

一元加法運(yùn)算符 +value,是大家熟知的將 value 轉(zhuǎn)換成數(shù)字類(lèi)型的方法。

為了避免混淆,在 bigint 中不支持一元加法:

let bigint = 1n;

alert( +bigint ); // error

所以我們應(yīng)該用 Number() 來(lái)將一個(gè) bigint 轉(zhuǎn)換成一個(gè)數(shù)字類(lèi)型。

比較運(yùn)算符

比較運(yùn)算符,例如 < 和 >,使用它們來(lái)對(duì) bigint 和 number 類(lèi)型的數(shù)字進(jìn)行比較沒(méi)有問(wèn)題:

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

alert( 2n > 1 ); // true

但是請(qǐng)注意,由于 number 和 bigint 屬于不同類(lèi)型,它們可能在進(jìn)行 == 比較時(shí)相等,但在進(jìn)行 ===(嚴(yán)格相等)比較時(shí)不相等:

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

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

布爾運(yùn)算

當(dāng)在 if 或其他布爾運(yùn)算中時(shí),bigint 的行為類(lèi)似于 number。

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

if (0n) {
  // 永遠(yuǎn)不會(huì)執(zhí)行
}

布爾運(yùn)算符,例如 ||,&& 和其他運(yùn)算符,處理 bigint 的方式也類(lèi)似于 number:

alert( 1n || 2 ); // 1(1n 被認(rèn)為是真)

alert( 0n || 2 ); // 2(0n 被認(rèn)為是假)

Polyfill

Polyfilling bigint 比較棘手。原因是許多 JavaScript 運(yùn)算符,比如 + 和 - 等,在對(duì)待 bigint 的行為上與常規(guī) number 相比有所不同。

例如,bigint 的除法總是返回 bigint(如果需要,會(huì)進(jìn)行舍入)。

想要模擬這種行為,polyfill 需要分析代碼,并用其函數(shù)替換所有此類(lèi)運(yùn)算符。但是這樣做很麻煩,并且會(huì)耗費(fèi)很多性能。

所以,目前并沒(méi)有一個(gè)眾所周知的好用的 polyfill。

不過(guò),JSBI 庫(kù)的開(kāi)發(fā)者提出了另一種解決方案。

該庫(kù)使用自己的方法實(shí)現(xiàn)了大的數(shù)字。我們可以使用它們替代原生的 bigint:

運(yùn)算 原生 BigInt JSBI
從 Number 創(chuàng)建 a = BigInt(789) a = JSBI.BigInt(789)
加法 c = a + b c = JSBI.add(a, b)
減法 c = a - b c = JSBI.subtract(a, b)

……然后,對(duì)于那些支持 bigint 的瀏覽器,可以使用 polyfill(Babel 插件)將 JSBI 調(diào)用轉(zhuǎn)換為原生的 bigint。

換句話說(shuō),這個(gè)方法建議我們?cè)趯?xiě)代碼時(shí)使用 JSBI 替代原生的 bigint。但是 JSBI 在內(nèi)部像使用 bigint 一樣使用 number,并最大程度按照規(guī)范進(jìn)行模擬,所以代碼已經(jīng)是準(zhǔn)備好轉(zhuǎn)換成 bigint 的了(bigint-ready)。

對(duì)于不支持 bigint 的引擎,我們可以“按原樣”使用此類(lèi) JSBI 代碼,對(duì)于那些支持 bigint 的引擎 —— polyfill 會(huì)將調(diào)用轉(zhuǎn)換為原生的 bigint。

參考


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)