js的第七种基本数据类型BigInt
js的第七种基本数据类型BigInt
BigInt 可能会成为⾃ ES2015 引⼊ Symbol 之后,增加的第⼀个新的内置类型。并且 BigInt 类型在 TypeScript3.2 版本被内置。。。本篇将简单记录下BigInt
js的第七种基本数据类型BigInt
js 采⽤双精度浮点数,这也导致了精度有限的问题。在 js 中,Number 基本类型可以精确表⽰的最⼤整数是 2^53。因此早期会有这如下的“bug”:
let max = Number.MAX_SAFE_INTEGER;// 最⼤安全整数
let max1 = max +1
let max2 = max +2
max1 === max2 //true
为了解决这个限制,BigInt出现在了ECMAScript标准中。
let max =BigInt(Number.MAX_SAFE_INTEGER);
let max1 = max +1n
let max2 = max +2n
max1 === max2 // false
介绍
BigInt 可以表⽰任意⼤的整数。
创建
语法:
BigInt(value);
其中参数:
value: 创建对象的数值。可以是字符串或者整数。
注意, BigInt() 不是构造函数,因此不能使⽤ new 操作符。
除了通过BigInt构造函数,我们还可以通过在⼀个整数字⾯量后⾯加 n 的⽅式定义⼀个 BigInt ,如:10n。
例:
let valA =10n;
let valB =BigInt(10);
console.log(valA === valB);// true
类型判断
我们可以通过typeof操作符来判断是否为BigInt类型(返回字符串"bigint"),如
typeof1n ==='bigint';// true
typeof BigInt('1')==='bigint';// true
同样的,我们也可以⽤最通⽤的String⽅法(返回字符串"[object BigInt]")
String.call(10n)==='[object BigInt]';// true
运算
以下操作符可以和 BigInt ⼀起使⽤: +、*、-、**、% 。除 >>> (⽆符号右移)之外的 位操作 也可以⽀持。(因为 BigInt 都是有符号的 >>> (⽆符号右移)不能⽤于 BigInt)。
为了兼容 asm.js ,.BigInt 不⽀持单⽬ (+) 运算符。
const previousMaxSafe =BigInt(Number.MAX_SAFE_INTEGER);
// 9007199254740991n
const maxPlusOne = previousMaxSafe +1n;
// 9007199254740992n
const theFuture = previousMaxSafe +2n;
// 9007199254740993n, this works now!
const multi = previousMaxSafe *2n;
// 18014398509481982n
const subtr = multi – 10n;
// 18014398509481972n
parameter数据类型const mod = multi %10n;
// 2n
const bigN =2n **54n;
// 18014398509481984n
bigN *-1n
// –18014398509481984n
当使⽤ BigInt 时,带⼩数的运算会被取整。
const expected =4n /2n;
/
/ 2n
const rounded =5n /2n;
// 2n, not 2.5n
⽅法
BigInt.asIntN()
将 BigInt 值转换为⼀个 -2^width - 1 与 2^(width-1) - 1 之间的有符号整数。
语法:
BigInt.asIntN(width, bigint);
如:
const max =2n **(64n -1n)-1n;
BigInt.asIntN(64, max);// 9223372036854775807n
BigInt.asIntN(64, max +1n);// -9223372036854775807n
// negative because of overflow
BigInt.asUintN()
将⼀个 BigInt 值转换为 0 与 2^width-1 之间的⽆符号整数。
语法:
BigInt.asUintN(width, bigint);
const max =2n **64n -1n;
BigInt.asUintN(64, max);
// 18446744073709551615n
BigInt.asUintN(64, max +1n);
// 0n
/
/ zero because of overflow
BigInt和Number
BigInt 和 Number 不是严格相等的,但是宽松相等的。
10n ===10
// false
10n ==10
// true
Number 和 BigInt 可以进⾏⽐较。
1n <2;// true
2n >1;// true
2>2;// false
2n >2;// false
2n >=2;// true
两者也可以混在⼀个数组内并排序。
const mixed =[4n,6,-12n,10,4,0,0n];// [4n, 6, -12n, 10, 4, 0, 0n]
mixed.sort();// [-12n, 0, 0n, 10, 4n, 4, 6]
BigInt 在需要转换成 Boolean 的时表现跟 Number 类似:如通过 Boolean 函数转换;⽤于 Logical Operators ||, &&, 和 ! 的操作数;或者⽤于在像 if statement 这样的条件语句中。
它在某些⽅⾯类似于 Number ,但是也有⼏个关键的不同点:不能⽤与 Math 对象中的⽅法;不能和任何 Number 实例混合运算,两者必须转换成同⼀种类型。在两种类型来回转换时要⼩⼼,因为 BigInt 变量在转换成 Number 变量时可能会丢失精度。
不允许隐式类型转换
因为隐式类型转换可能丢失信息,所以不允许在bigint和 Number 之间进⾏混合操作。当混合使⽤⼤整数和浮点数时,结果值可能⽆法由BigInt或Number精确表⽰。
如:
10n +1;// Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions
Math.max(2n,4n,6n);//
BigInt和String
难免会遇到数字和字符串的转换,BigInt也不例外,不过可惜的是BigInt转为String时,其标志性的n会被省略,如
String(10n);// '10'
''+11n;// '11'
因此也导致以下情况:
// array
let arr =[1,2,3,4,5];
arr[2]=== arr[2n];// true
// object
let obj ={
'1':'1',
'2':'2',
'3':'3',
'4':'4'
};
obj['1']=== obj[1n];// true
零值
BigInt 没有 Number 的正零(+0)和负零(-0)之分。因为 BigInt 表⽰的是整数
⽆穷和NaN判断
很有趣的现象
isFinite(10n);// Uncaught TypeError: Cannot convert a BigInt value to a number
Number.isFinite(10n);// false
isNaN(10n);// Uncaught TypeError: Cannot convert a BigInt value to a number
Number.isNaN(10n);// false
由此我们可以看出isFinite()和Number.isFinite()、isNaN()和Number.isNaN()的区别:isFinite(val)/isNaN(val)的⼯作机制都是讲参数值val转为数值后再进⾏⽐较判断,⽽Number.isFinite(val)/Number.isNaN(val)则可以理解为直接简单粗暴的变量全等判断(val === Infinity/val === NaN)
兼容
(⾄2019.11.11兼容情况)
[外链图⽚转存失败,源站可能有防盗链机制,建议将图⽚保存下来直接上传(img-GFNZO7Qn-1573652653106)
(/images/notes/20191111/compatibility.png)]
如图,兼容情况并不是很好。并且转换BigInt是⼀个极其复杂的过程,这会导致严重的运⾏时性能损失。直接polyfill BigInt也是不可能的,因为该提议改变了⼏个现有操作符的⾏为。⽬前,更好的选择是使⽤JSBI库,它是BigInt提案的纯JS实现,。
使⽤如下:
import JSBI from'./jsbi.mjs';
const max =JSBI.BigInt(Number.MAX_SAFE_INTEGER);
console.log(String(max));
// → '9007199254740991'
const other =JSBI.BigInt('2');
const result =JSBI.add(max, other);
console.log(String(result));
// → '9007199254740993'
TypeScript
BigInt 类型在 TypeScript3.2 版本被内置,
在TypeScript中,BigInt 和 Number 都是有表⽰数字的意思,但是实际上两者类型是不同的:
declare let valA: number;
declare let valB: bigint;
valA = valB; // error: Type 'bigint' is not assignable to type 'number'.
valB = valA; // error: Type 'number' is not assignable to type 'bigint'.
除了类型定义,TypeScript 中 BigInt 其他使⽤⽅法同 ES。
相关链接