ECMAScript 6之數值的擴展

ECMAScript 6之數值的擴展

1. 二進制和八進制的表示

ES6 提供了二進制和八進制數值的新的寫法,分別用前綴0b(或0B)和0o(或0O)表示。

// 數值轉爲二進制字符
(369).toString(2); // "101110001"
// 數值轉爲八進制字符
369..toString(8); // "561"

// 二進制用0b或oB表示
0b101110001 === 369; // true
0B101110001 === 369; // true

// 八進制用0o或0O表示
0o561 === 369; // true
0O561 === 369; // true

上面代碼中,數值369沒有直接調用toString()方法,如果不加括號直接調用toString(),這個點會被 JavaScript 引擎解釋成小數點,從而報錯。有以下方法可以避免這個問題。

  • 數值加上括號(()
  • 在數值後面加兩個點,JavaScript 會把第一個點理解成小數點,把第二個點理解成調用對象屬性,從而得到正確結果
  • 通過方括號運算符([])調用
// 數值加()調用
(234).toString(2); // "11101010"
// 數值加.調用
234..toString(2); // "11101010"
// 通過[]調用
234['toString'](2); // "11101010"

2. Number.isFinite(), Number.isNaN()

ES6 在Number對象上,提供了Number.isFinite()Number.isNaN()兩個方法。Number.isFinite()用來檢查一個數值是否爲有限的;Number.isNaN()用來檢查一個數值是否爲NaN

// Number.isFinite()檢查一個數是否是有限的
Number.isFinite(15); // true
Number.isFinite(0.8); // true

// 參數類型不是數值,一律返回false
Number.isFinite(NaN); // false
Number.isFinite(Infinity); // false
Number.isFinite(-Infinity); // false
Number.isFinite('jidi'); // false
Number.isFinite('1'); // false
Number.isFinite(true); // false


// Number.isNaN()檢查一個數是否爲NaN
Number.isNaN(NaN) // true
Number.isNaN(9/NaN) // true
Number.isNaN('true' / 0) // true
Number.isNaN('true' / 'true') // true

// 參數類型不是NaN,一律返回false
Number.isNaN(15) // false
Number.isNaN('15') // false
Number.isNaN(true) // false

注意:·Number.isFinite()的參數類型如果不是數值,一律返回falseNumber.isNan()的參數如果不是NaN,一律返回true

2.1 Number.isFinite(),Number.isNaN()與全局方法isFinite(),isNaN()的區別

全局方法isFinite()isNaN()會先調用Number()方法將非數值類型的參數轉換爲數據類型的值,然後再進行判斷,而Number.isFinite()Number.isNaN()兩個方法只對數值有效。Number.isFinite()的參數如果不是數值類型,一律返回falseNumber.isNaN()的參數非NaN一律返回true

// isFinite()會先調用Number方法進行數據類型轉換,然後進行判斷
isFinite(25); // true
isFinite("25"); // true

// Number.isFinite()只對數值有效
Number.isFinite(25); // true
Number.isFinite("25"); // false

// isNaN()會先調用Number方法進行數據類型轉換,然後進行判斷
isNaN(NaN) // true
isNaN("NaN") // true

// Number.isNaN()只對數值有效
Number.isNaN(NaN) // true
Number.isNaN("NaN") // false
Number.isNaN(1) // false

3. Number.parseInt(),Number.parseFloat()

ES6 將全局方法parseInt()parseFloat(),移植到了Number對象上面,行爲完全保持不變。

// ES5寫法
parseInt('123'); // 123
parseInt('   81'); // 81
parseInt(1.23); // 1
parseInt('8a'); // 8
parseInt('12**'); // 12
parseInt('12.34'); // 12
parseInt('15e2'); // 15
parseInt('15px'); // 15
parseInt('abc'); // NaN
parseInt('.3'); // NaN
parseInt(''); // NaN
parseInt('+'); // NaN
parseInt('1000', 2); // 8
parseInt('1000', 6); // 216
parseInt('1000', 8); // 512

// ES6寫法
Number.parseInt('123'); // 123
Number.parseInt('   81'); // 81
Number.parseInt(1.23); // 1
Number.parseInt('8a'); // 8
Number.parseInt('12**'); // 12
Number.parseInt('12.34'); // 12
Number.parseInt('15e2'); // 15
Number.parseInt('15px'); // 15
Number.parseInt('abc'); // NaN
Number.parseInt('.3'); // NaN
Number.parseInt(''); // NaN
Number.parseInt('+'); // NaN
Number.parseInt('1000', 2); // 8
Number.parseInt('1000', 6); // 216
Number.parseInt('1000', 8); // 512

4. Number.isInteger()

Number.isInteger()用來判斷一個數值是否爲整數。

Number.isInteger(5); // true
Number.isInteger(5.0); // true
Number.isInteger(5.6); // false

上面代碼中,55.0結果一樣,因爲javaScript內部,整數和浮點數用的同一種存儲方法(參考JavaScript教程)。

根據國際標準 IEEE 754,JavaScript 提供的有效數字最長爲53個二進制位。當數值的精度超過這個標準,Number.isInteger()會失真。

// 超過精度範圍,判斷失真
Number.isInteger(1.000000000000000000000000000000000000002); // true

5. Number.EPSILON

ES6 新增一個極小的常量Number.EPSILON,它表示 1 與大於1的最小浮點數之間的差。由於數字在javaScript內部使用64位浮點數存儲,所以Number.EPSILON相當於2-52次方。

Number.EPSILON === Math.pow(2, -52); // true
Number.EPSILON; // 2.220446049250313e-16

由於浮點數的計算是不精確的,Number.EPSILON的實質是一個可以接受的最小誤差範圍。

// 浮點數的計算是不精確的
0.1 + 0.7; // 0.7999999999999999

// 在最小誤差範圍內,可以認爲兩個數相等
2 + Number.EPSILON === 2;

6. 安全整數和 Number.isSafeInteger()

JavaScript 能夠準確表示的整數範圍在-253253之間(開區間),超過這個範圍,無法精確表示這個值。
ES6 引入了Number.MAX_SAFE_INTEGERNumber.MIN_SAFE_INTEGER這兩個常量,用來表示這個範圍的上下限。Number.isSafeInteger()則是用來判斷一個整數是否落在這個範圍之內.。

Math.pow(2, 53) - 1; // 9007199254740991
Number.MAX_SAFE_INTEGER === Math.pow(2, 53) - 1; // true
Number.MAX_SAFE_INTEGER === 9007199254740991; // true

Number.MIN_SAFE_INTEGER === -Number.MAX_SAFE_INTEGER; // true
Number.MIN_SAFE_INTEGER === -9007199254740991; // true

// 判斷一個數是否在-9007199254740991~9007199254740991之間
Number.isSafeInteger('jidi'); // false
Number.isSafeInteger(null); // false
Number.isSafeInteger(NaN); // false
Number.isSafeInteger(Infinity); // false
Number.isSafeInteger(-Infinity); // false

Number.isSafeInteger(3); // true
Number.isSafeInteger(1.2); // false
Number.isSafeInteger(9007199254740990); // true
Number.isSafeInteger(9007199254740992); // false

Number.isSafeInteger(Number.MIN_SAFE_INTEGER - 1); // false
Number.isSafeInteger(Number.MIN_SAFE_INTEGER); // true
Number.isSafeInteger(Number.MAX_SAFE_INTEGER); // true
Number.isSafeInteger(Number.MAX_SAFE_INTEGER + 1); // false

注意:使用Number.isSafeInteger()函數進行驗證時,不要只驗證運算結果,而要同時驗證參與運算的每個值

7. 指數運算符

ES2016 新增了一個指數運算符(**)。**是右結合的,多個指數運算可以連用。

2 ** 2; // 4
2 ** 3; // 8

// 多個指數運算符連用
2 ** 3 ** 2; // 512

8. BigInt 數據類型

由於JavaScript 所有數字都用64 位浮點數進行存儲,數值的精度只能到 53 個二進制位,而且大於或等於21024次方的數值(小於或等於-21023次方的數值),JavaScript 無法表示,會返回Infinity-Infinity)。

// 超過 53 個二進制位的數值,無法保持精度
Math.pow(2, 53) === Math.pow(2, 53) + 1; // true

// 超過 2 的 1024 次方的數值,無法表示
Math.pow(2, 1025); // Infinity

ES2020 引入了一種新的數據類型 BigInt,來解決這個問題。BigInt 只用來表示整數,沒有位數的限制,任何位數的整數都可以精確表示。BigInt 類型的數據必須添加後綴n

// Bigint數據後面加後綴n
const a = 21721416122353n;
const b = 153463491231309n;

// BigInt精度可以保證
a*b; // 3333444352624333556168350077n

Bigint類型的數據與普通數值是兩種值,並不相等。

const c1 = 12n;
const c2 = 12;

typeof c1; // "bigint"
typeof c2; // "number"

// 兩者不相等
c1 === c2; // false

8.1 BigInt 對象

JavaScript 原生提供BigInt對象,可以用作構造函數生成 BigInt 類型的數值。BigInt()構造函數必須有參數,而且參數必須可以正常轉爲數值。

// 用法參照Number()
BigInt(123) // 123n
BigInt('123') // 123n
BigInt(false) // 0n
BigInt(true) // 1n

// Bigint()必須有參數,且參數必須能轉爲數值
new BigInt(); // Uncaught TypeError: BigInt is not a constructor at new BigInt 
BigInt(undefined); // Uncaught TypeError: Cannot convert undefined to a BigInt
BigInt(null); // Uncaught TypeError: Cannot convert null to a BigInt at BigInt 
BigInt(NaN); // Uncaught RangeError: The number NaN cannot be converted to a BigInt because it is not an integer
BigInt(Infinity); // Uncaught RangeError: The number Infinity cannot be converted to a BigInt because it is not an integer at BigInt

BigInt()構造函數參數不能爲小數。

BigInt(1.1); // Uncaught RangeError: The number 1.1 cannot be converted to a BigInt because it is not an integer at BigInt 

BigInt 類型的+-***這四個二元運算符,與 Number 類型的行爲一致。除法運算/會捨去小數部分,返回一個整數。

12n + 12n; // 24n
2n * 2n; // 4n
12n - 2n; // 10n
2n ** 3n; // 8n

// 除法會捨去小數部分,返回整數
10n / 6n; // 1n

BigInt 不能與普通數值進行混合運算。

1n + 32; // Uncaught TypeError: Cannot mix BigInt and other types

有兩個數值運算符不能用在Bigint數據類型的值上。

  • 無符號右移>>>
  • 一元求正+

>>>是無符號右移,而Bigint數據類型的總是帶符號的,所以該運算無意義;而一元+運算符結果是返回Number的,會報錯。

+ 12n; // Uncaught TypeError: Cannot convert a BigInt value to a number

跟一元求正運算符一樣,如果一個標準庫函數的參數預期是Number 類型,但是得到的是一個 BigInt,就會報錯。

Math.pow(2n, 2); // Uncaught TypeError: Cannot convert a BigInt value to a number  at Math.pow
Math.abs(4n); // Uncaught TypeError: Cannot convert a BigInt value to a number at Math.abs

9. 參考鏈接

本篇博文是我自己學習筆記,原文請參考:ECMAScript 6 入門
如有問題,請及時指出!
歡迎溝通交流,郵箱:[email protected]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章