今天想起了js新增的基本資料型別,就去上網查閱了一番,在此做個總結,
首先我們要了解它是干什么的,BigInt資料型別的目的是比Number資料型別支持的范圍更大的整數值以任意精度表示整數的能力尤為重要,使用BigInt,整數溢位將不再是問題,
因為在js中的數字型別是按照IEEE 754-2008標準的定義,所有數字都以雙精度64位浮點格式表示,因為在IEEE 754標準下浮點數的舍入模式是一下4類:
| 最近舍入 | 即向距離最近的浮點數舍入,若存在兩個同樣接近的數,則選擇偶數作為舍入值 |
|---|---|
| 向零舍入 | 又稱截斷舍入,將多余的精度位截掉,即取舍入后絕對值較小的值 |
| 正向舍入 | 也稱正無窮舍入,即舍入后結果大于原值 |
| 負向舍入 | 也稱負無窮舍入,即舍入后結果小于原值 |
所以在此標準下,無法精確表示的非常大的整數將自動四舍五入,確切地說,JS 中的Number型別只能安全地表示-9007199254740991 (-(2^53-1))和9007199254740991(2^53-1)之間的整數,任何超出此范圍的整數值都可能失去精度,
console.log(9999999999999999); //10000000000000000
因為該整數大于JS Number型別所能表示的最大整數,所以它被四舍五入了,意外的四舍五入會損害程式的可靠性和安全性,例如:
// 注意最后一位的數字
9007199254740992 === 9007199254740993; //true
原因是因為,JS提供Number.MAX_SAFE_INTEGER常量表示最大安全整數,Number.MIN_SAFE_INTEGER常量表示最小安全整數,
可以把它列印出來:
const minInt = Number.MIN_SAFE_INTEGER;
console.log(minInt); //-9007199254740991
console.log(minInt - 5); //-9007199254740996
// 注意它是如何輸出與上面相同的值的
console.log(minInt - 4); // -9007199254740996
解決方案
使用 bignumber.js 處理大整數
使用 BigInt 應用程式不再需要變通方法或庫來安全地表示Number.MAX_SAFE_INTEGER和Number.Min_SAFE_INTEGER之外的整數, 現在可以在標準JS中執行對大整數的算術運算,而不會有精度損失的風險,
要創建BigInt,只需在整數的末尾追加n即可,比如:
console.log(9007199254740995n); //9007199254740995n
console.log(9007199254740995); //9007199254740996
或者可以呼叫 BigInt() 建構式
BigInt("9007199254740995"); //9007199254740995n
BigInt建構式
與其他基本型別一樣,可以使用建構式創建BigInt,傳遞給BigInt()的引數將自動轉換為BigInt
BigInt("10"); //10n
BigInt(10); //10n
BigInt(true); //1n
無法轉換的資料型別和值會引發例外
BigInt(10.2); //RangeError
BigInt(null); //TypeError
BigInt("abc"); //SyntaxError
可以直接對使用建構式創建的BigInt執行算術操作
BigInt(10) * 10n; //100n
在使用嚴格相等運算子時,使用建構式創建的BigInt 與常規BigInt 的處理方式類似
BigInt(true) === 1n; //true
console.log( 1n == true) //true
BigInt 也可以用二進制,八進制或十六進制表示
// binary 二進制
console.log(0b100000000000000000000000000000000000000000000000000011n);
//9007199254740995n
// hex 十六進制
console.log(0x20000000000003n);
//9007199254740995n
// octal 八進制
console.log(0o400000000000000003n);
//9007199254740995n
// 注意,不支持遺留的八進制語法
console.log(0400000000000000003n);
//SyntaxError 語法錯誤
不能使用嚴格相等運算子將BigInt與常規數字進行比較,因為它們的型別不同, 如下:
console.log(1n === 1); //false
console.log(typeof 10n); //bigint
console.log(typeof 10); //number
但在使用等號運算子,它在處理操作之前執行隱式轉換
console.log(1n == 1); //true
除了一元加號(+)運算子外,所有的算術運算子都可以用于BigInt
1n + 20; //3n
1n - 2n; //-1n
+10n; //語法錯誤
//TypeError: Cannot convert a BigInt value
//to a number:不能將BigInt值轉換為數字
-1n; //-1n
1n * 2n; //2n
2n / 2n; //1n
10n % 3n; //1n
10n ** 2n; //100n
var a = 1n;
++a; //2n
--a; //0n
不支持一元加號(+)運算子的原因是某些程式可能依賴于+始終生成Number的不變數,或者拋出例外, 更改+的行為也會破壞asm.js代碼,
當然, BigInt 進行算術運算子的操作時回傳的是 `BigInt值,因此,除法運算子的結果會自動向下舍入到最接近的整數, 如:
15 / 10; //1.5
15n / 10n //1n
隱式轉換
因為隱式轉換可能會導致資訊丟失,所以不允許在 BigInt 和 Number 之間進行混合操作,當混合使用大整數和浮點數時,結果可能無法由 BigInt 或 Number 精確表示,如:
console.log((9007199254740992n + 1n) + 0.5)
//拋出錯誤:不能混合使用BigInt和其他型別,請使用顯式轉換
這個運算式的結果超出了BigInt和Number的范圍,小數部分的Number不能精確地轉換為BigInt,大于2^53的BigInt不能準確地轉換為數字,
由于這個限制,不可能對混合使用Number和BigInt運算元執行算術操作,還不能將BigInt傳遞給Web api和內置的 JS 函式,這些函式需要一個 Number 型別的數字,嘗試這樣做會報TypeError型別錯誤
console.log(10 + 10n); //TypeError
console.log(Math.max(1n, 2n, 3n)); //TypeError
但是關系運算子不遵循改規則
console.log(2n > 1); //true
如果使用到BigInt和Number執行算術計算的話,首先要確定在哪個型別下進行操作
BigInt(5) + 10n; //15n
//或者
5 + Number(10n) //15
當BigInt 和 Boolean型別一起使用時,方法和Number類似
if(2n) {
//要執行的邏輯
}
如果判斷是0n時則無效
if(0n) {
//大括號里的邏輯將不會執行
}
在進行BigInts和Numbers陣列的排序時,不會發生隱式型別轉換
const arr = [3n, 4, 2, 1n, 0, -1n];
arr.sort(); //[-1n, 0, 1n, 2, 3n, 4]
顯示轉換和隱式轉換
隱式轉換就是系統默認的、不需要加以宣告就可以進行的轉換,一般情況下,資料的型別的轉換通常是由編譯系統自動進行的,不需要人工干預,所以被稱為隱式型別轉換,但如果程式要求一定要將某一型別的資料轉換為另外一種型別,則可以利用強制型別轉換運算子進行轉換,這種強制轉換程序稱為顯式轉換,
總結
BigInt是一種新的資料型別,用于當整數值大于Number資料型別支持的范圍時,這種資料型別允許我們安全地對大整數執行算術操作,表示高解析度的時間戳,使用大整數id,等等,而不需要使用庫,
不能使用Number和BigInt運算元的混合執行算術運算,需要通過顯式轉換其中的一種型別, 此外,出于兼容性原因,不允許在BigInt上使用一元加號(+)運算子,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/250171.html
標籤:其他
上一篇:MySQL常用陳述句
下一篇:MySql 常用的函式
