<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          ECMAScript 6 入門教程—數(shù)值的擴展

          共 3611字,需瀏覽 8分鐘

           ·

          2020-09-12 05:41

          作者 | 阮一峰


          1、二進制和八進制表示法

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

          0b111110111 === 503 // true
          0o767 === 503 // true

          從 ES5 開始,在嚴格模式之中,八進制就不再允許使用前綴0表示,ES6 進一步明確,要使用前綴0o表示。

          // 非嚴格模式
          (function(){
          console.log(0o11 === 011);
          })() // true

          // 嚴格模式
          (function(){
          'use strict';
          console.log(0o11 === 011);
          })() // Uncaught SyntaxError: Octal literals are not allowed in strict mode.

          如果要將0b和0o前綴的字符串數(shù)值轉為十進制,要使用Number方法。

          Number('0b111')  // 7
          Number('0o10') // 8

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

          ES6 在Number對象上,新提供了Number.isFinite()和Number.isNaN()兩個方法。

          Number.isFinite()用來檢查一個數(shù)值是否為有限的(finite),即不是Infinity。

          Number.isFinite(15); // true
          Number.isFinite(0.8); // true
          Number.isFinite(NaN); // false
          Number.isFinite(Infinity); // false
          Number.isFinite(-Infinity); // false
          Number.isFinite('foo'); // false
          Number.isFinite('15'); // false
          Number.isFinite(true); // false

          注意,如果參數(shù)類型不是數(shù)值,Number.isFinite一律返回false。

          Number.isNaN()用來檢查一個值是否為NaN。

          Number.isNaN(NaN) // true
          Number.isNaN(15) // false
          Number.isNaN('15') // false
          Number.isNaN(true) // false
          Number.isNaN(9/NaN) // true
          Number.isNaN('true' / 0) // true
          Number.isNaN('true' / 'true') // true

          如果參數(shù)類型不是NaN,Number.isNaN一律返回false。

          它們與傳統(tǒng)的全局方法isFinite()和isNaN()的區(qū)別在于,傳統(tǒng)方法先調用Number()將非數(shù)值的值轉為數(shù)值,再進行判斷,而這兩個新方法只對數(shù)值有效,Number.isFinite()對于非數(shù)值一律返回false, Number.isNaN()只有對于NaN才返回true,非NaN一律返回false。

          isFinite(25) // true
          isFinite("25") // true
          Number.isFinite(25) // true
          Number.isFinite("25") // false

          isNaN(NaN) // true
          isNaN("NaN") // true
          Number.isNaN(NaN) // true
          Number.isNaN("NaN") // false
          Number.isNaN(1) // false

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

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

          // ES5的寫法
          parseInt('12.34') // 12
          parseFloat('123.45#') // 123.45

          // ES6的寫法
          Number.parseInt('12.34') // 12
          Number.parseFloat('123.45#') // 123.45

          這樣做的目的,是逐步減少全局性方法,使得語言逐步模塊化。

          Number.parseInt === parseInt // true
          Number.parseFloat === parseFloat // true

          4、Number.isInteger()

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

          Number.isInteger(25) // true
          Number.isInteger(25.1) // false

          JavaScript 內部,整數(shù)和浮點數(shù)采用的是同樣的儲存方法,所以 25 和 25.0 被視為同一個值。

          Number.isInteger(25) // true
          Number.isInteger(25.0) // true

          如果參數(shù)不是數(shù)值,Number.isInteger返回false。

          Number.isInteger() // false
          Number.isInteger(null) // false
          Number.isInteger('15') // false
          Number.isInteger(true) // false

          注意,由于 JavaScript 采用 IEEE 754 標準,數(shù)值存儲為64位雙精度格式,數(shù)值精度最多可以達到 53 個二進制位(1 個隱藏位與 52 個有效位)。

          如果數(shù)值的精度超過這個限度,第54位及后面的位就會被丟棄,這種情況下,Number.isInteger可能會誤判。

          Number.isInteger(3.0000000000000002) // true

          上面代碼中,Number.isInteger的參數(shù)明明不是整數(shù),但是會返回true。原因就是這個小數(shù)的精度達到了小數(shù)點后16個十進制位,轉成二進制位超過了53個二進制位,導致最后的那個2被丟棄了。

          類似的情況還有,如果一個數(shù)值的絕對值小于Number.MIN_VALUE(5E-324),即小于 JavaScript 能夠分辨的最小值,會被自動轉為 0。這時,Number.isInteger也會誤判。

          Number.isInteger(5E-324) // false
          Number.isInteger(5E-325) // true

          上面代碼中,5E-325由于值太小,會被自動轉為0,因此返回true。

          總之,如果對數(shù)據(jù)精度的要求較高,不建議使用Number.isInteger()判斷一個數(shù)值是否為整數(shù)。

          5、Number.EPSILON

          ES6 在Number對象上面,新增一個極小的常量Number.EPSILON。根據(jù)規(guī)格,它表示 1 與大于 1 的最小浮點數(shù)之間的差。

          對于 64 位浮點數(shù)來說,大于 1 的最小浮點數(shù)相當于二進制的1.00..001,小數(shù)點后面有連續(xù) 51 個零。這個值減去 1 之后,就等于 2 的 -52 次方。

          Number.EPSILON === Math.pow(2, -52)
          // true
          Number.EPSILON
          // 2.220446049250313e-16
          Number.EPSILON.toFixed(20)
          // "0.00000000000000022204"

          Number.EPSILON實際上是 JavaScript 能夠表示的最小精度。誤差如果小于這個值,就可以認為已經(jīng)沒有意義了,即不存在誤差了。

          引入一個這么小的量的目的,在于為浮點數(shù)計算,設置一個誤差范圍。我們知道浮點數(shù)計算是不精確的。

          0.1 + 0.2
          // 0.30000000000000004

          0.1 + 0.2 - 0.3
          // 5.551115123125783e-17

          5.551115123125783e-17.toFixed(20)
          // '0.00000000000000005551'

          上面代碼解釋了,為什么比較0.1 + 0.2與0.3得到的結果是false。

          0.1 + 0.2 === 0.3 // false

          Number.EPSILON可以用來設置“能夠接受的誤差范圍”。比如,誤差范圍設為 2 的-50 次方(即Number.EPSILON * Math.pow(2, 2)),即如果兩個浮點數(shù)的差小于這個值,我們就認為這兩個浮點數(shù)相等。

          5.551115123125783e-17 < Number.EPSILON * Math.pow(2, 2)
          // true

          因此,Number.EPSILON的實質是一個可以接受的最小誤差范圍。

          function withinErrorMargin (left, right) {
          return Math.abs(left - right) < Number.EPSILON * Math.pow(2, 2);
          }

          0.1 + 0.2 === 0.3 // false
          withinErrorMargin(0.1 + 0.2, 0.3) // true

          1.1 + 1.3 === 2.4 // false
          withinErrorMargin(1.1 + 1.3, 2.4) // true

          上面的代碼為浮點數(shù)運算,部署了一個誤差檢查函數(shù)。

          6、安全整數(shù)和 Number.isSafeInteger()

          JavaScript 能夠準確表示的整數(shù)范圍在-2^532^53之間(不含兩個端點),超過這個范圍,無法精確表示這個值。

          Math.pow(2, 53) // 9007199254740992

          9007199254740992 // 9007199254740992
          9007199254740993 // 9007199254740992

          Math.pow(2, 53) === Math.pow(2, 53) + 1
          // true

          上面代碼中,超出 2 的 53 次方之后,一個數(shù)就不精確了。

          ES6 引入了Number.MAX_SAFE_INTEGERNumber.MIN_SAFE_INTEGER這兩個常量,用來表示這個范圍的上下限。

          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

          上面代碼中,可以看到 JavaScript 能夠精確表示的極限。

          Number.isSafeInteger()則是用來判斷一個整數(shù)是否落在這個范圍之內。

          Number.isSafeInteger('a') // 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

          這個函數(shù)的實現(xiàn)很簡單,就是跟安全整數(shù)的兩個邊界值比較一下。

          Number.isSafeInteger = function (n) {
          return (typeof n === 'number' &&
          Math.round(n) === n &&
          Number.MIN_SAFE_INTEGER <= n &&
          n <= Number.MAX_SAFE_INTEGER);
          }

          實際使用這個函數(shù)時,需要注意。驗證運算結果是否落在安全整數(shù)的范圍內,不要只驗證運算結果,而要同時驗證參與運算的每個值。

          Number.isSafeInteger(9007199254740993)
          // false
          Number.isSafeInteger(990)
          // true
          Number.isSafeInteger(9007199254740993 - 990)
          // true
          9007199254740993 - 990
          // 返回結果 9007199254740002
          // 正確答案應該是 9007199254740003

          上面代碼中,9007199254740993不是一個安全整數(shù),但是Number.isSafeInteger會返回結果,顯示計算結果是安全的。這是因為,這個數(shù)超出了精度范圍,導致在計算機內部,以9007199254740992的形式儲存。

          9007199254740993 === 9007199254740992
          // true

          所以,如果只驗證運算結果是否為安全整數(shù),很可能得到錯誤結果。下面的函數(shù)可以同時驗證兩個運算數(shù)和運算結果。

          function trusty (left, right, result) {
          if (
          Number.isSafeInteger(left) &&
          Number.isSafeInteger(right) &&
          Number.isSafeInteger(result)
          ) {
          return result;
          }
          throw new RangeError('Operation cannot be trusted!');
          }

          trusty(9007199254740993, 990, 9007199254740993 - 990)
          // RangeError: Operation cannot be trusted!

          trusty(1, 2, 3)
          // 3

          7、Math 對象的擴展

          ES6 在 Math 對象上新增了 17 個與數(shù)學相關的方法。所有這些方法都是靜態(tài)方法,只能在 Math 對象上調用。

          Math.trunc()

          Math.trunc方法用于去除一個數(shù)的小數(shù)部分,返回整數(shù)部分。

          Math.trunc(4.1) // 4
          Math.trunc(4.9) // 4
          Math.trunc(-4.1) // -4
          Math.trunc(-4.9) // -4
          Math.trunc(-0.1234) // -0

          對于非數(shù)值,Math.trunc內部使用Number方法將其先轉為數(shù)值。

          Math.trunc('123.456') // 123
          Math.trunc(true) //1
          Math.trunc(false) // 0
          Math.trunc(null) // 0

          對于空值和無法截取整數(shù)的值,返回NaN

          Math.trunc(NaN);      // NaN
          Math.trunc('foo'); // NaN
          Math.trunc(); // NaN
          Math.trunc(undefined) // NaN

          對于沒有部署這個方法的環(huán)境,可以用下面的代碼模擬。

          Math.trunc = Math.trunc || function(x) {
          return x < 0 ? Math.ceil(x) : Math.floor(x);
          };

          Math.sign()

          Math.sign方法用來判斷一個數(shù)到底是正數(shù)、負數(shù)、還是零。對于非數(shù)值,會先將其轉換為數(shù)值。

          它會返回五種值。

          • 參數(shù)為正數(shù),返回+1

          • 參數(shù)為負數(shù),返回-1

          • 參數(shù)為 0,返回0

          • 參數(shù)為-0,返回-0;

          • 其他值,返回NaN

          Math.sign(-5) // -1
          Math.sign(5) // +1
          Math.sign(0) // +0
          Math.sign(-0) // -0
          Math.sign(NaN) // NaN

          如果參數(shù)是非數(shù)值,會自動轉為數(shù)值。對于那些無法轉為數(shù)值的值,會返回NaN

          Math.sign('')  // 0
          Math.sign(true) // +1
          Math.sign(false) // 0
          Math.sign(null) // 0
          Math.sign('9') // +1
          Math.sign('foo') // NaN
          Math.sign() // NaN
          Math.sign(undefined) // NaN

          對于沒有部署這個方法的環(huán)境,可以用下面的代碼模擬。

          Math.sign = Math.sign || function(x) {
          x = +x; // convert to a number
          if (x === 0 || isNaN(x)) {
          return x;
          }
          return x > 0 ? 1 : -1;
          };

          Math.cbrt()

          Math.cbrt()方法用于計算一個數(shù)的立方根。

          Math.cbrt(-1) // -1
          Math.cbrt(0) // 0
          Math.cbrt(1) // 1
          Math.cbrt(2) // 1.2599210498948732

          對于非數(shù)值,Math.cbrt()方法內部也是先使用Number()方法將其轉為數(shù)值。

          Math.cbrt('8') // 2
          Math.cbrt('hello') // NaN

          對于沒有部署這個方法的環(huán)境,可以用下面的代碼模擬。

          Math.cbrt = Math.cbrt || function(x) {
          var y = Math.pow(Math.abs(x), 1/3);
          return x < 0 ? -y : y;
          };

          Math.clz32()

          Math.clz32()方法將參數(shù)轉為 32 位無符號整數(shù)的形式,然后返回這個 32 位值里面有多少個前導 0。

          Math.clz32(0) // 32
          Math.clz32(1) // 31
          Math.clz32(1000) // 22
          Math.clz32(0b01000000000000000000000000000000) // 1
          Math.clz32(0b00100000000000000000000000000000) // 2

          上面代碼中,0 的二進制形式全為 0,所以有 32 個前導 0;1 的二進制形式是0b1,只占 1 位,所以 32 位之中有 31 個前導 0;1000 的二進制形式是0b1111101000,一共有 10 位,所以 32 位之中有 22 個前導 0。

          clz32這個函數(shù)名就來自”count leading zero bits in 32-bit binary representation of a number“(計算一個數(shù)的 32 位二進制形式的前導 0 的個數(shù))的縮寫。

          左移運算符(<<)與Math.clz32方法直接相關。

          Math.clz32(0) // 32
          Math.clz32(1) // 31
          Math.clz32(1 << 1) // 30
          Math.clz32(1 << 2) // 29
          Math.clz32(1 << 29) // 2

          對于小數(shù),Math.clz32方法只考慮整數(shù)部分。

          Math.clz32(3.2) // 30
          Math.clz32(3.9) // 30

          對于空值或其他類型的值,Math.clz32方法會將它們先轉為數(shù)值,然后再計算。

          Math.clz32() // 32
          Math.clz32(NaN) // 32
          Math.clz32(Infinity) // 32
          Math.clz32(null) // 32
          Math.clz32('foo') // 32
          Math.clz32([]) // 32
          Math.clz32({}) // 32
          Math.clz32(true) // 31

          Math.imul()

          Math.imul方法返回兩個數(shù)以 32 位帶符號整數(shù)形式相乘的結果,返回的也是一個 32 位的帶符號整數(shù)。

          Math.imul(2, 4)   // 8
          Math.imul(-1, 8) // -8
          Math.imul(-2, -2) // 4

          如果只考慮最后 32 位,大多數(shù)情況下,Math.imul(a, b)a * b的結果是相同的,即該方法等同于(a * b)|0的效果(超過 32 位的部分溢出)。之所以需要部署這個方法,是因為 JavaScript 有精度限制,超過 2 的 53 次方的值無法精確表示。這就是說,對于那些很大的數(shù)的乘法,低位數(shù)值往往都是不精確的,Math.imul方法可以返回正確的低位數(shù)值。

          (0x7fffffff * 0x7fffffff)|0 // 0

          上面這個乘法算式,返回結果為 0。但是由于這兩個二進制數(shù)的最低位都是 1,所以這個結果肯定是不正確的,因為根據(jù)二進制乘法,計算結果的二進制最低位應該也是 1。這個錯誤就是因為它們的乘積超過了 2 的 53 次方,JavaScript 無法保存額外的精度,就把低位的值都變成了 0。Math.imul方法可以返回正確的值 1。

          Math.imul(0x7fffffff, 0x7fffffff) // 1

          Math.fround()

          Math.fround方法返回一個數(shù)的32位單精度浮點數(shù)形式。

          對于32位單精度格式來說,數(shù)值精度是24個二進制位(1 位隱藏位與 23 位有效位),所以對于 -224?至 224?之間的整數(shù)(不含兩個端點),返回結果與參數(shù)本身一致。

          Math.fround(0)   // 0
          Math.fround(1) // 1
          Math.fround(2 ** 24 - 1) // 16777215

          如果參數(shù)的絕對值大于 224,返回的結果便開始丟失精度。

          Math.fround(2 ** 24)       // 16777216
          Math.fround(2 ** 24 + 1) // 16777216

          Math.fround方法的主要作用,是將64位雙精度浮點數(shù)轉為32位單精度浮點數(shù)。如果小數(shù)的精度超過24個二進制位,返回值就會不同于原值,否則返回值不變(即與64位雙精度值一致)。

          // 未丟失有效精度
          Math.fround(1.125) // 1.125
          Math.fround(7.25) // 7.25

          // 丟失精度
          Math.fround(0.3) // 0.30000001192092896
          Math.fround(0.7) // 0.699999988079071
          Math.fround(1.0000000123) // 1

          對于?NaN?和?Infinity,此方法返回原值。對于其它類型的非數(shù)值,Math.fround?方法會先將其轉為數(shù)值,再返回單精度浮點數(shù)。

          Math.fround(NaN)      // NaN
          Math.fround(Infinity) // Infinity

          Math.fround('5') // 5
          Math.fround(true) // 1
          Math.fround(null) // 0
          Math.fround([]) // 0
          Math.fround({}) // NaN

          對于沒有部署這個方法的環(huán)境,可以用下面的代碼模擬。

          Math.fround = Math.fround || function (x) {
          return new Float32Array([x])[0];
          };

          Math.hypot()

          Math.hypot方法返回所有參數(shù)的平方和的平方根。

          Math.hypot(3, 4);        // 5
          Math.hypot(3, 4, 5); // 7.0710678118654755
          Math.hypot(); // 0
          Math.hypot(NaN); // NaN
          Math.hypot(3, 4, 'foo'); // NaN
          Math.hypot(3, 4, '5'); // 7.0710678118654755
          Math.hypot(-3); // 3

          上面代碼中,3 的平方加上 4 的平方,等于 5 的平方。

          如果參數(shù)不是數(shù)值,Math.hypot方法會將其轉為數(shù)值。只要有一個參數(shù)無法轉為數(shù)值,就會返回 NaN。

          對數(shù)方法

          ES6 新增了 4 個對數(shù)相關方法。

          (1) Math.expm1()

          Math.expm1(x)返回 ex - 1,即Math.exp(x) - 1。

          Math.expm1(-1) // -0.6321205588285577
          Math.expm1(0) // 0
          Math.expm1(1) // 1.718281828459045

          對于沒有部署這個方法的環(huán)境,可以用下面的代碼模擬。

          Math.expm1 = Math.expm1 || function(x) {
          return Math.exp(x) - 1;
          };

          (2)Math.log1p()

          Math.log1p(x)方法返回1 + x的自然對數(shù),即Math.log(1 + x)。如果x小于-1,返回NaN。

          Math.log1p(1)  // 0.6931471805599453
          Math.log1p(0) // 0
          Math.log1p(-1) // -Infinity
          Math.log1p(-2) // NaN

          對于沒有部署這個方法的環(huán)境,可以用下面的代碼模擬。

          Math.log1p = Math.log1p || function(x) {
          return Math.log(1 + x);
          };

          (3)Math.log10()

          Math.log10(x)返回以 10 為底的x的對數(shù)。如果x小于 0,則返回 NaN。

          Math.log10(2)      // 0.3010299956639812
          Math.log10(1) // 0
          Math.log10(0) // -Infinity
          Math.log10(-2) // NaN
          Math.log10(100000) // 5

          對于沒有部署這個方法的環(huán)境,可以用下面的代碼模擬。

          Math.log10 = Math.log10 || function(x) {
          return Math.log(x) / Math.LN10;
          };

          (4)Math.log2()

          Math.log2(x)返回以 2 為底的x的對數(shù)。如果x小于 0,則返回 NaN。

          Math.log2(3)       // 1.584962500721156
          Math.log2(2) // 1
          Math.log2(1) // 0
          Math.log2(0) // -Infinity
          Math.log2(-2) // NaN
          Math.log2(1024) // 10
          Math.log2(1 << 29) // 29

          對于沒有部署這個方法的環(huán)境,可以用下面的代碼模擬。

          Math.log2 = Math.log2 || function(x) {
          return Math.log(x) / Math.LN2;
          };

          雙曲函數(shù)方法

          ES6 新增了 6 個雙曲函數(shù)方法。

          • Math.sinh(x)?返回x的雙曲正弦(hyperbolic sine)

          • Math.cosh(x)?返回x的雙曲余弦(hyperbolic cosine)

          • Math.tanh(x)?返回x的雙曲正切(hyperbolic tangent)

          • Math.asinh(x)?返回x的反雙曲正弦(inverse hyperbolic sine)

          • Math.acosh(x)?返回x的反雙曲余弦(inverse hyperbolic cosine)

          • Math.atanh(x)?返回x的反雙曲正切(inverse hyperbolic tangent)

          8、指數(shù)運算符

          ES2016 新增了一個指數(shù)運算符(**)。

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

          這個運算符的一個特點是右結合,而不是常見的左結合。多個指數(shù)運算符連用時,是從最右邊開始計算的。

          // 相當于 2 ** (3 ** 2)
          2 ** 3 ** 2
          // 512

          上面代碼中,首先計算的是第二個指數(shù)運算符,而不是第一個。

          指數(shù)運算符可以與等號結合,形成一個新的賦值運算符(**=)。

          let a = 1.5;
          a **= 2;
          // 等同于 a = a * a;

          let b = 4;
          b **= 3;
          // 等同于 b = b * b * b;

          9、BigInt 數(shù)據(jù)類型

          簡介

          JavaScript 所有數(shù)字都保存成 64 位浮點數(shù),這給數(shù)值的表示帶來了兩大限制。一是數(shù)值的精度只能到 53 個二進制位(相當于 16 個十進制位),大于這個范圍的整數(shù),JavaScript 是無法精確表示的,這使得 JavaScript 不適合進行科學和金融方面的精確計算。二是大于或等于2的1024次方的數(shù)值,JavaScript 無法表示,會返回Infinity。

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

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

          ES2020?引入了一種新的數(shù)據(jù)類型 BigInt(大整數(shù)),來解決這個問題,這是 ECMAScript 的第八種數(shù)據(jù)類型。BigInt 只用來表示整數(shù),沒有位數(shù)的限制,任何位數(shù)的整數(shù)都可以精確表示。

          const a = 2172141653n;
          const b = 15346349309n;

          // BigInt 可以保持精度
          a * b // 33334444555566667777n

          // 普通整數(shù)無法保持精度
          Number(a) * Number(b) // 33334444555566670000

          為了與 Number 類型區(qū)別,BigInt 類型的數(shù)據(jù)必須添加后綴n。

          1234 // 普通整數(shù)
          1234n // BigInt

          // BigInt 的運算
          1n + 2n // 3n

          BigInt 同樣可以使用各種進制表示,都要加上后綴n。

          0b1101n // 二進制
          0o777n // 八進制
          0xFFn // 十六進制

          BigInt 與普通整數(shù)是兩種值,它們之間并不相等。

          42n === 42 // false

          typeof運算符對于 BigInt 類型的數(shù)據(jù)返回bigint。

          typeof 123n // 'bigint'

          BigInt 可以使用負號(-),但是不能使用正號(+),因為會與 asm.js 沖突。

          -42n // 正確
          +42n // 報錯

          JavaScript 以前不能計算70的階乘(即70!),因為超出了可以表示的精度。

          let p = 1;
          for (let i = 1; i <= 70; i++) {
          p *= i;
          }
          console.log(p); // 1.197857166996989e+100

          現(xiàn)在支持大整數(shù)了,就可以算了,瀏覽器的開發(fā)者工具運行下面代碼,就OK。

          let p = 1n;
          for (let i = 1n; i <= 70n; i++) {
          p *= i;
          }
          console.log(p); // 11978571...00000000n

          BigInt 對象

          JavaScript 原生提供BigInt對象,可以用作構造函數(shù)生成 BigInt 類型的數(shù)值。轉換規(guī)則基本與Number()一致,將其他類型的值轉為 BigInt。

          BigInt(123) // 123n
          BigInt('123') // 123n
          BigInt(false) // 0n
          BigInt(true) // 1n

          BigInt()構造函數(shù)必須有參數(shù),而且參數(shù)必須可以正常轉為數(shù)值,下面的用法都會報錯。

          new BigInt() // TypeError
          BigInt(undefined) //TypeError
          BigInt(null) // TypeError
          BigInt('123n') // SyntaxError
          BigInt('abc') // SyntaxError

          上面代碼中,尤其值得注意字符串123n無法解析成 Number 類型,所以會報錯。

          參數(shù)如果是小數(shù),也會報錯。

          BigInt(1.5) // RangeError
          BigInt('1.5') // SyntaxError

          BigInt 對象繼承了 Object 對象的兩個實例方法。

          • BigInt.prototype.toString()

          • BigInt.prototype.valueOf()

          它還繼承了 Number 對象的一個實例方法。

          • BigInt.prototype.toLocaleString()

          此外,還提供了三個靜態(tài)方法。

          • BigInt.asUintN(width, BigInt):給定的 BigInt 轉為 0 到 2width - 1 之間對應的值。

          • BigInt.asIntN(width, BigInt):給定的 BigInt 轉為 -2width - 1 到 2width - 1 - 1 之間對應的值。

          • BigInt.parseInt(string[, radix]):近似于Number.parseInt(),將一個字符串轉換成指定進制的 BigInt。

          const max = 2n ** (64n - 1n) - 1n;

          BigInt.asIntN(64, max)
          // 9223372036854775807n
          BigInt.asIntN(64, max + 1n)
          // -9223372036854775808n
          BigInt.asUintN(64, max + 1n)
          // 9223372036854775808n

          上面代碼中,max是64位帶符號的 BigInt 所能表示的最大值。如果對這個值加1n,BigInt.asIntN()將會返回一個負值,因為這時新增的一位將被解釋為符號位。而BigInt.asUintN()方法由于不存在符號位,所以可以正確返回結果。

          如果BigInt.asIntN()和BigInt.asUintN()指定的位數(shù),小于數(shù)值本身的位數(shù),那么頭部的位將被舍棄。

          const max = 2n ** (64n - 1n) - 1n;

          BigInt.asIntN(32, max) // -1n
          BigInt.asUintN(32, max) // 4294967295n

          上面代碼中,max是一個64位的 BigInt,如果轉為32位,前面的32位都會被舍棄。

          下面是BigInt.parseInt()的例子。

          // Number.parseInt() 與 BigInt.parseInt() 的對比
          Number.parseInt('9007199254740993', 10)
          // 9007199254740992
          BigInt.parseInt('9007199254740993', 10)
          // 9007199254740993n

          上面代碼中,由于有效數(shù)字超出了最大限度,Number.parseInt方法返回的結果是不精確的,而BigInt.parseInt方法正確返回了對應的 BigInt。

          對于二進制數(shù)組,BigInt 新增了兩個類型BigUint64Array和BigInt64Array,這兩種數(shù)據(jù)類型返回的都是64位 BigInt。DataView對象的實例方法DataView.prototype.getBigInt64()和DataView.prototype.getBigUint64(),返回的也是 BigInt。

          轉換規(guī)則

          可以使用Boolean()、Number()和String()這三個方法,將 BigInt 可以轉為布爾值、數(shù)值和字符串類型。

          Boolean(0n) // false
          Boolean(1n) // true
          Number(1n) // 1
          String(1n) // "1"

          上面代碼中,注意最后一個例子,轉為字符串時后綴n會消失。

          另外,取反運算符(!)也可以將 BigInt 轉為布爾值。

          !0n // true
          !1n // false

          數(shù)學運算

          數(shù)學運算方面,BigInt 類型的+、-、*和**這四個二元運算符,與 Number 類型的行為一致。除法運算/會舍去小數(shù)部分,返回一個整數(shù)。

          9n / 5n
          // 1n

          幾乎所有的數(shù)值運算符都可以用在 BigInt,但是有兩個例外。

          • 不帶符號的右移位運算符>>>

          • 一元的求正運算符+

          上面兩個運算符用在 BigInt 會報錯。前者是因為>>>運算符是不帶符號的,但是 BigInt 總是帶有符號的,導致該運算無意義,完全等同于右移運算符>>。后者是因為一元運算符+在 asm.js 里面總是返回 Number 類型,為了不破壞 asm.js 就規(guī)定+1n會報錯。

          BigInt 不能與普通數(shù)值進行混合運算。

          1n + 1.3 // 報錯

          上面代碼報錯是因為無論返回的是 BigInt 或 Number,都會導致丟失精度信息。比如(2n**53n + 1n) + 0.5這個表達式,如果返回 BigInt 類型,0.5這個小數(shù)部分會丟失;如果返回 Number 類型,有效精度只能保持 53 位,導致精度下降。

          同樣的原因,如果一個標準庫函數(shù)的參數(shù)預期是 Number 類型,但是得到的是一個 BigInt,就會報錯。

          // 錯誤的寫法
          Math.sqrt(4n) // 報錯

          // 正確的寫法
          Math.sqrt(Number(4n)) // 2

          上面代碼中,Math.sqrt的參數(shù)預期是 Number 類型,如果是 BigInt 就會報錯,必須先用Number方法轉一下類型,才能進行計算。

          asm.js 里面,|0跟在一個數(shù)值的后面會返回一個32位整數(shù)。根據(jù)不能與 Number 類型混合運算的規(guī)則,BigInt 如果與|0進行運算會報錯。

          1n | 0 // 報錯

          其他運算

          BigInt 對應的布爾值,與 Number 類型一致,即0n會轉為false,其他值轉為true。

          if (0n) {
          console.log('if');
          } else {
          console.log('else');
          }
          // else

          上面代碼中,0n對應false,所以會進入else子句。

          比較運算符(比如>)和相等運算符(==)允許 BigInt 與其他類型的值混合計算,因為這樣做不會損失精度。

          0n < 1 // true
          0n < true // true
          0n == 0 // true
          0n == false // true
          0n === 0 // false

          BigInt 與字符串混合運算時,會先轉為字符串,再進行運算。

          '' + 123n // "123"


          本文完


          推薦閱讀

          ECMAScript 6 入門教程
          ECMAScript 6 入門教程——let 和 const 命令
          ECMAScript 6 入門教程—字符串的擴展
          ECMAScript 6 入門教程—字符串的新增方法
          ECMAScript 6 入門教程—正則的擴展

          瀏覽 27
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日本伦理一区二区三区 | 中文天堂av | 东京热黄色录像大全 | 一级性爱视频免费看 | 青娱乐在线视频2 |