13.数字

本章介绍 JavaScript 的单一类型数字,number。

13.1 JavaScript 只有浮点数

您可以在 JavaScript 中表示整数和浮点数:

98
123.45

但是,所有数字只有一种类型:它们都是双精度 ,根据 IEEE 浮点运算标准(IEEE 754)实现的 64 位浮点数。

整数只是没有小数部分的浮点数:

> 98 === 98.0
true

请注意,在大多数情况下,大多数 JavaScript 引擎通常都能够使用实际整数,并具有所有相关的性能和存储大小优势。

13.2 数字字面值

让我们检查数字的字面值。

13.2.1 。整数字面值

几个整数字面值 让你用各种基数表示整数:

// Binary (base 2)
assert.equal(0b11, 3);
// Octal (base 8)
assert.equal(0o10, 8);
// Decimal (base 10):
assert.equal(35, 35);
// Hexadecimal (base 16)
assert.equal(0xE7, 231);

13.2.2 浮点字面值

浮点数只能用基数 10 表示。

分数:

> 35.0
35

指数:eN表示10 ** N

> 3e2
300
> 3e-2
0.03
> 0.3e2
30

13.2.3 语法缺陷:整数字面值的属性

访问整数字面值的属性会带来陷阱:如果整数字面值后面紧跟一个点,则该点被解释为小数点:

7.toString(); // syntax error

有四种方法可以解决这个陷阱:

7.0.toString()
(7).toString()
7..toString()
7 .toString()  // space before dot

13.3 数字运算符

13.3.1 二元算术运算符

assert.equal(1 + 4, 5); // addition
assert.equal(6 - 3, 3); // subtraction
assert.equal(2 * 1.25, 2.5); // multiplication
assert.equal(6 / 4, 1.5); // division
assert.equal(6 % 4, 2); // remainder
assert.equal(2 ** 3, 8); // exponentiation

%是余数运算符(不是模运算符) - 其结果具有第一个操作数的符号:

> 3 % 2
1
> -3 % 2
-1

13.3.2 一元加法和相反数

assert.equal(+(-3), -3); // unary plus
assert.equal(-(-3), 3); // unary negation

两个运算符都将他们的操作数强制转换为数字:

> +'7'
7
> +'-12'
-12
> -'9'
-9

13.3.3 自增(++)和自减(--

自增运算符++存在前缀版本和后缀版本。在这两个版本中,它破坏性地将其操作数加一。因此,其操作数必须是可以更改的存储位置。自减运算符--的工作方式相同,但从其操作数中减一。接下来的两个示例解释了前缀和后缀版本之间的区别。

前缀++和前缀--:更改然后返回。

let foo = 3;
assert.equal(++foo, 4);
assert.equal(foo, 4);
let bar = 3;
assert.equal(--bar, 2);
assert.equal(bar, 2);

后缀++和后缀--:返回然后更改。

let foo = 3;
assert.equal(foo++, 3);
assert.equal(foo, 4);
let bar = 3;
assert.equal(bar--, 3);
assert.equal(bar, 2);
13.3.3.1 操作数:不仅仅是变量

您还可以将这些运算符应用于属性值:

const obj = { a: 1 };
++obj.a;
assert.equal(obj.a, 2);

并且用于数组元素:

const arr = [ 4 ];
arr[0]++;
assert.deepEqual(arr, [5]);

练习:数字运算符

exercises/numbers-math/is_odd_test.js

13.4 转换为数字

这些是将值转换为数字的三种方法:

  • Number(value)
  • +value
  • parseFloat(value)(避免;与其他两个不同!)

建议:使用描述性Number()

assert.equal(Number(undefined), NaN);
assert.equal(Number(null), 0);
assert.equal(Number(false), 0);
assert.equal(Number(true), 1);
assert.equal(Number(123), 123);
assert.equal(Number(''), 0);
assert.equal(Number('123'), 123);
assert.equal(Number('xyz'), NaN);

可以配置如何将对象转换为数字。例如,通过覆盖.valueOf()

> Number({ valueOf() { return 123 } })
123

练习:转换为数字

exercises/numbers-math/parse_number_test.js

13.5 错误值

发生错误时返回两个数字值:

  • NaN
  • Infinity

13.6 错误值:NaN

NaN是“非数字”的缩写。具有讽刺意味的是,JavaScript 认为它是一个数字:

> typeof NaN
'number'

什么时候返回NaN

如果无法解析数字,则返回NaN

> Number('$$$')
NaN
> Number(undefined)
NaN

如果无法执行操作,则返回NaN

> Math.log(-1)
NaN
> Math.sqrt(-1)
NaN

如果操作数或参数是NaN(传播错误),则返回NaN

> NaN - 3
NaN
> 7 ** NaN
NaN

13.6.1 检查NaN

NaN是唯一不严格等于自己的 JavaScript 值:

const n = NaN;
assert.equal(n === n, false);

这些是检查值x是否为NaN的几种方法:

const x = NaN;
assert.equal(Number.isNaN(x), true); // preferred
assert.equal(Object.is(x, NaN), true);
assert.equal(x !== x, true);

在最后一行,我们使用比较小技巧来检测NaN

13.6.2在数组中查找NaN

有些数组方法找不到NaN

> [NaN].indexOf(NaN)
-1

其他可以:

> [NaN].includes(NaN)
true
> [NaN].findIndex(x => Number.isNaN(x))
0
> [NaN].find(x => Number.isNaN(x))
NaN

唉,没有简单的经验法则,你必须检查每个方法,它如何处理NaN

13.7 错误值:Infinity

何时返回错误值Infinity

如果数字太大,则返回无穷大:

> Math.pow(2, 1023)
8.98846567431158e+307
> Math.pow(2, 1024)
Infinity

如果除以零,则返回无穷大:

> 5 / 0
Infinity
> -5 / 0
-Infinity

13.7.1 Infinity作为默认值

Infinity大于所有其他数字(NaN除外),使其成为一个很好的默认值:

function findMinimum(numbers) {
  let min = Infinity;
  for (const n of numbers) {
    if (n < min) min = n;
  }
  return min;
}
assert.equal(findMinimum([5, -1, 2]), -1);
assert.equal(findMinimum([]), Infinity);

13.7.2 检查Infinity

这是检查值x是否为Infinity的两种常用方法:

const x = Infinity;
assert.equal(x === Infinity, true);
assert.equal(Number.isFinite(x), false);

练习:比较数字

exercises/numbers-math/find_max_test.js

13.8 数字的精确度:小心小数

在内部,JavaScript 浮点数用基数 2 表示(根据 IEEE 754 标准)。这意味着小数部分(基数 10)不能总是精确表示:

> 0.1 + 0.2
0.30000000000000004
> 1.3 * 3
3.9000000000000004
> 1.4 * 100000000000000
139999999999999.98

因此,在 JavaScript 中执行算术时需要考虑舍入误差。

13.9 高级

本章的所有其余部分都是高级的。

13.10 背景:浮点精度

JavaScript 中,使用数字进行计算并不总能产生精确的结果。例如:

> 0.1 + 0.2
0.30000000000000004

要理解原因,我们需要探索 JavaScript 如何在内部表示浮点数。它使用三个整数来执行此操作,如表 5 中所述。

表 5:在内部,JavaScript 使用三个整数来表示浮点数。它们总共占用 64 位存储空间(双精度)。

成分 大小 整数范围
符号 1 位 [0,1]
小数 52 位 [0,2 ** 52 -1]
指数 11 位 [-1023,1024]

由这些整数表示的浮点数计算如下:

(-1) ** 符号 * 0b1.小数 * 2 ** 指数

为了进一步讨论,我们简化了这种表示:

  • 我们使用基数 10(十进制)代替基数 2(二进制),因为这是大多数人更熟悉的。
  • 小数 是一个解释为小数的自然数(一个点后的数字)。我们切换到尾数 ,这是一个被解释为自身的整数。因此,指数的使用方式不同,但其基本作用不会改变。
  • 由于尾数是一个整数(有自己的符号),我们不再需要单独的符号了。

新表示的工作方式如下:

尾数 * 10 ** 指数

让我们试试几个浮点数的表示。

  • 对于整数-123,我们主要需要尾数:
    > -123 * (10 ** 0)
    - 123
    
  • 对于数字1.5,我们想象尾数后面有一个点。我们使用负指数将该点向左移动一位:
    > 15 * (10 ** -1)
    1.5
    
  • 对于数字0.25,我们将点向右移动两位数:
    > 25 * (10 ** -2)
    0.25
    

具有负指数的表示也可以写为分母中具有正指数的分数:

> 15 * (10 ** -1) === 15 / 10
true
> 25 * (10 ** -2) === 25 / 100
true

这些分数有助于理解为什么我们的编码无法表示数字:

  • 可以表示1/10。它已经具有所需的格式:分母是 10 的幂。
  • 1/2可以表示为5/10。我们通过将分子和分母乘以 5,将分母中的 2 变为 10 的幂。
  • 1/4可以表示为25/100。通过将分子和分母乘以 25,我们将分母中的 4 变为 10 的幂。
  • 1/3无法表示。没有办法将分母变为 10 的幂。(10 的素数因子是 2 和 5。因此,任何只有这些素数因子的分母都可以通过使用足够的二和五乘以分子和分母,来转换为 10 的幂。如果分母有不同的素因子,那么我们无能为力。)

为了结束游览,我们切换回基数 2:

  • 0.5 = 1/2可以用基数 2 表示,因为分母已经是 2 的幂。
  • 0.25 = 1/4可以用基数 2 表示,因为分母已经是 2 的幂。
  • 无法表示0.1 = 1/10,因为分母无法转换为 2 的幂。
  • 无法表示0.2 = 2/10,因为分母无法转换为 2 的幂。

现在我们可以看到为什么0.1 + 0.2不能产生精确的结果:在内部,两个操作数都不能精确表示。

精确计算小数分数的唯一方法是通过内部切换到基数 10。对于许多编程语言,基数 2 是默认值,基数 10 是一个选项。例如,Java 具有类BigDecimal ,Python 具有模块 decimal。JavaScript 暂时有计划添加类似的东西:ECMAScript 提案“Decimal”目前在阶段 0

13.11 JavaScript 中的整数

JavaScript 没有特殊的整数类型。相反,它们只是没有小数部分的正常(浮点)数字:

> 1 === 1.0
true
> Number.isInteger(1.0)
true

在本节中,我们将介绍一些使用这些伪整数的工具。

13.11.1 转换为整数

将数字转换为整数的推荐方法是使用Math对象的一种舍入方法:

  • Math.floor(n):返回i ≤ n的最大整数
    > Math.floor(2.1)
    2
    > Math.floor(2.9)
    2
    
  • Math.ceil(n):返回i ≥ n的最小整数
    > Math.ceil(2.1)
    3
    > Math.ceil(2.9)
    3
    
  • Math.round(n):返回“最接近”n的整数。0.5 向上舍入。例如:
    > Math.round(2.4)
    2
    > Math.round(2.5)
    3
    
  • Math.trunc(n):删除n具有的任何小数部分(在小数点之后),因此将其转换为整数。
    > Math.trunc(2.1)
    2
    > Math.trunc(2.9)
    2
    

表 6 显示这些函数的各种输入的结果。

表 6: 将数字转换为整数的函数。 注意事情如何随负数变化,因为“较大”总是意味着“接近正无穷大”。

-2.9 -2.5 -2.1 2.1 2.5 2.9
Math.floor -3 -3 -3 2 2 2
Math.ceil -2 -2 -2 3 3 3
Math.round -3 -2 -2 2 3 3
Math.trunc -2 -2 -2 2 2 2

13.11.2 JavaScript 中的整数范围

这些是 JavaScript 中重要的整数范围:

  • 安全整数: 可以通过 JavaScript“安全地”表示(意味着什么后面会讲更多)
    • 精度:53 位带符号
    • 范围:(-2 ** 53 ~ 2 ** 53)
  • 数组索引
    • 精度:32 位,无符号
    • 范围:[0, 2 ** 32 - 1)(不包括最大长度)
    • 类型数组有更大的 53 位范围(安全和无符号)
  • 按位操作数 (按位或,等等)
    • 精度:32 位
    • 无符号右移范围(>>>):无符号,[0, 2 ** 32)
    • 所有其他按位运算符的范围:有符号,[-2 ** 31, 2 ** 31)

13.11.3 安全整数

这是 JavaScript安全 的整数范围:

[-2 ** 53 - 1, 2 ** 53 - 1]

如果一个整数是安全 的,则它只由一个 JavaScript 数字表示。鉴于 JavaScript 数字被编码为小数乘以二的指数次幂,也可以表示更高的整数,但它们之间存在间隙。

例如(18014398509481984 是2 ** 54):

> 18014398509481984
18014398509481984
> 18014398509481985
18014398509481984
> 18014398509481986
18014398509481984
> 18014398509481987
18014398509481988

Number的以下属性有助于确定整数是否安全:

assert.equal(Number.MAX_SAFE_INTEGER, (2 ** 53) - 1);
assert.equal(Number.MIN_SAFE_INTEGER, -Number.MAX_SAFE_INTEGER);
assert.equal(Number.isSafeInteger(5), true);
assert.equal(Number.isSafeInteger('5'), false);
assert.equal(Number.isSafeInteger(5.1), false);
assert.equal(Number.isSafeInteger(Number.MAX_SAFE_INTEGER), true);
assert.equal(Number.isSafeInteger(Number.MAX_SAFE_INTEGER+1), false);

练习:检测安全整数

exercises/numbers-math/is_safe_integer_test.js

13.11.3.1 安全的计算

让我们看一下涉及不安全整数的计算。

以下结果不正确且不安全,即使它的两个操作数都是安全的。

> 9007199254740990 + 3
9007199254740992

以下结果是安全的,但不正确。第一个操作数是不安全的,第二个操作数是安全的。

> 9007199254740995 - 10
9007199254740986

因此,当且仅当两个操作数和结果都是安全的时,表达式a op b的结果才是正确的:

isSafeInteger(a) && isSafeInteger(b) && isSafeInteger(a op b)

13.12 按位运算符

JavaScript 按位运算符的工作方式如下:

  • 首先,操作数转换为数字(64 位双浮点数),然后转换为 32 位整数。
  • 然后执行按位操作。
  • 最后,结果将转换回双精度并返回。

在内部,运算符使用以下整数范围(输入和输出):

  • 无符号右移运算符(>>>):32 位,范围[0, 2 ** 32)
  • 所有其他按位运算符:32 位包括符号,范围[-2 ** 31, 2 ** 31)

如果我们以二进制表示法将它们显示为无符号 32 位整数,则其中一些运算符的结果最容易理解。这就是b32()的作用(其实现将在后面显示):

assert.equal(
  b32(-1),
  '11111111111111111111111111111111');
assert.equal(
  b32(1),
  '00000000000000000000000000000001');
assert.equal(
  b32(2 ** 31),
  '10000000000000000000000000000000');

13.12.1 二元按位运算符

表 7:二进制按位运算符

运算符 名称
num1 & num2 按位和
`num1 num2`
num1 ^ num2 按位异或

二元运算符(表 7 )组合其操作数的位来产生它们的结果:

> (0b1010 & 0b11).toString(2).padStart(4, '0')
'0010'
> (0b1010 | 0b11).toString(2).padStart(4, '0')
'1011'
> (0b1010 ^ 0b11).toString(2).padStart(4, '0')
'1001'

13.12.2 按位非

表 8 :按位非

运算符 名称
~num 按位非,补码

按位非运算符(表 8)反转其操作数的每个二进制位:

> b32(~0b100)
'11111111111111111111111111111011'

13.12.3 移位运算符

表 9:移位运算符

运算符 名称
num << count 左移
num >> count 有符号右移
num >>> count 无符号右移

移位运算符(表 9)向左或向右移动二进制位:

> (0b10 << 1).toString(2)
'100'

>>保留最高位,>>>不保留:

> b32(0b10000000000000000000000000000010 >> 1)
'11000000000000000000000000000001'
> b32(0b10000000000000000000000000000010 >>> 1)
'01000000000000000000000000000001'

13.12.4 b32():以二进制表示法显示 32 位整数

我们现在使用了b32()几次。以下代码是它的实现。

/**
 * Return a string representing n as a 32-bit unsigned integer,
 * in binary notation.
 */
function b32(n) {
  // >>> ensures highest bit isn’t interpreted as a sign
  return (n >>> 0).toString(2).padStart(32, '0');
}
assert.equal(
  b32(6),
  '00000000000000000000000000000110');

n >>> 0表示我们将n零位向右移位。因此,原则上,>>>运算符不执行任何操作,但它仍然将n强制转换为无符号的 32 位整数:

> 12 >>> 0
12
> -12 >>> 0
4294967284
> (2**32 + 1) >>> 0
1

13.13 快速参考:数字

13.13.1 转换为数字

表 10 显示如果通过Number()将各种值转换为数字会发生什么。表 10:将值转换为数字

x Number(x)
undefined NaN
null 0
布尔值 false → 0true → 1
数字 x(无变化)
字符串 '' → 0
其他 → 解析的数字,忽略前导/尾随空格
对象 可配置的(例如通过.valueOf()

13.13.2 算术运算符

JavaScript 有以下算术运算符:

  • 二元算术运算符(表 11)
  • 前缀和后缀算术运算符(表 12)

表 11:二元算术运算符

运算符 名称 示例
n + m 加法 ES1 3 + 4 → 7
n - m 减法 ES1 9 - 1 → 8
n * m 乘法 ES1 3 * 2.25 → 6.75
n / m 除法 ES1 5.625 / 5 → 1.125
n % m 余数 ES1 8 % 5 → 3
-8 % 5 → -3
n ** m ES2016 4 ** 2 → 16

表 12:前缀和后缀算术运算符

运算符 名称 示例
+n 一元加 ES1 +(-7) → -7
-n 一元减 ES1 -(-7) → 7
v++ 自增 ES1 let v=0; [v++, v] → [0, 1]
++v 自增 ES1 let v=0; [++v, v] → [1, 1]
v-- 自减 ES1 let v=1; [v--, v] → [1, 0]
--v 自减 ES1 let v=1; [--v, v] → [0, 0]

13.13.3 按位运算符

JavaScript 具有以下按位运算符:

  • 按位和,或,异或,非(表 13)
  • 移位运算符(表 14)

按位运算符的操作数和结果:

  • 无符号右移运算符(>>>):32 位,范围[0, 2 ** 32)
  • 所有其他按位运算符:32 位带符号,范围[-2 ** 31, 2 ** 31)

显示二进制数的辅助函数b32()在本章前面的章节中显示。

表 13:按位和,或,异或,非

运算符 名称 示例
i & j 按位和 ES1 (0b1010 & 0b1100).toString(2) → '1000'
`i j` 按位或 ES1
i ^ j 按位异或 ES1 (0b1010 ^ 0b0011).toString(2) → '1001'
~i 按位非 ES1 ~0b11111111111111111111111111111110 → 1

表 14:移位运算符

运算符 名称 示例
i << j 左移 ES1 (0b1 << 1).toString(2) → '10'
i >> j 符号右移 ES1 b32(0b10000000000000000000000000000010 >> 1)
→ '11000000000000000000000000000001'
i >>> j 无符号右移 ES1 b32(0b10000000000000000000000000000010 >>> 1)
→ '01000000000000000000000000000001'

13.13.4 数字的全局函数

JavaScript 具有以下四个全局函数:

  • isFinite()
  • isNaN()
  • parseFloat()
  • parseInt()

但是,最好使用Number的相应方法,这些方法具有较少的陷阱:Number.isFinite()Number.isNaN()Number.parseFloat()Number.parseInt()。它们是与 ES6 一起引入的,将在下面讨论。

13.13.5 Number的静态属性

  • .EPSILON: number ^[ES6]^ 1 和下一个可表示的浮点数之间的差异。通常,机器的 epsilon 为浮点运算中的舍入误差提供上限。
    • 大约为:2.2204460492503130808472633361816 * 10 ** (-16)
  • .MAX_SAFE_INTEGER: number ^[ES6]^ JavaScript 可以明确表示的最大整数(2 ** 53 - 1)。
  • .MAX_VALUE: number ^[ES1]^ 最大的正有限 JavaScript 数。
    • 大约为:1.7976931348623157 * 10 ** 308
  • .MIN_SAFE_INTEGER: number ^[ES6]^ JavaScript 可以明确表示的最小整数(-2 ** 53 + 1)。
  • .MIN_VALUE: number ^[ES1]^ 最小的 JavaScript 正数。大约5 * 10 ** -324
  • .NaN: number ^[ES1]^ 与全局变量NaN相同。
  • .NEGATIVE_INFINITY: number ^[ES1]^ 与-Number.POSITIVE_INFINITY相同。
  • .POSITIVE_INFINITY: number ^[ES1]^ 与全局变量Infinity相同。

13.13.6 Number的静态方法

  • .isFinite(num: number): boolean ^[ES6]^ 如果num是实际数字(不是Infinity-InfinityNaN),则返回true
    > Number.isFinite(Infinity)
    false
    > Number.isFinite(-Infinity)
    false
    > Number.isFinite(NaN)
    false
    > Number.isFinite(123)
    true
    
  • .isInteger(num: number): boolean ^[ES6]^ 如果num是一个数字并且没有小数部分,则返回true
    > Number.isInteger(-17)
    true
    > Number.isInteger(33)
    true
    > Number.isInteger(33.1)
    false
    > Number.isInteger('33')
    false
    > Number.isInteger(NaN)
    false
    > Number.isInteger(Infinity)
    false
    
  • .isNaN(num: number): boolean ^[ES6]^ 如果num是值NaN,则返回true
    > Number.isNaN(NaN)
    true
    > Number.isNaN(123)
    false
    > Number.isNaN('abc')
    false
    
  • .isSafeInteger(num: number): boolean ^[ES6]^ 如果num是一个数字并且明确表示一个整数,则返回true
  • .parseFloat(str: string): number ^[ES6]^ 将其参数强制转换为字符串并将其解析为浮点数。为了将字符串转换为数字,Number()(忽略前导和尾随空格)通常是比Number.parseFloat()更好的选择(它忽略前导空格和非法尾随字符并且可以隐藏问题)。
    > Number.parseFloat(' 123.4#')
    123.4
    > Number(' 123.4#')
    NaN
    
  • .parseInt(str: string, radix=10): number ^[ES6]^ 将其参数强制转换为字符串并将其解析为整数,忽略前导空格和非法尾随字符:
    > Number.parseInt('  123#')
    123
    
    参数radix指定要解析的数字的基数:
    > Number.parseInt('101', 2)
    5
    > Number.parseInt('FF', 16)
    255
    
    不要使用此方法将数字转换为整数:强制转换为字符串是低效的。并且在第一个非数字之前停止,不是用于移除数字的小数的良好算法。这是一个出错的例子:
    > Number.parseInt(1e21, 10) // wrong
    1
    
    最好使用Math的一个舍入函数将数字转换为整数:
    > Math.trunc(1e21) // correct
    1e+21
    

13.13.7 Number.prototype的方法

  • .toExponential(fractionDigits?: number): string ^[ES3]^ 返回一个字符串,该字符串通过指数表示法表示数字。使用fractionDigits,您可以指定与指数相乘的数字的位数(默认值是根据需要显示位数)。 示例:数字太小而无法通过.toString()获得正指数。
    > 1234..toString()
    '1234'
    > 1234..toExponential()
    '1.234e+3'
    > 1234..toExponential(5)
    '1.23400e+3'
    
    示例:数字太小而无法通过.toString()得到负指数。
    > 0.003.toString()
    '0.003'
    > 0.003.toExponential()
    '3e-3'
    > 0.003.toExponential(4)
    '3.0000e-3'
    
  • .toFixed(fractionDigits=0): string ^[ES3]^ 返回数字的无指数表示,舍入为fractionDigits个数字。
    > 0.0000003.toString()
    '3e-7'
    > 0.0000003.toFixed(10)
    '0.0000003000'
    > 0.0000003.toFixed()
    '0'
    
    如果数字为10 ** 21 或更高,则.toFixed()使用指数:
    > (10 ** 21).toFixed()
    '1e+21'
    
  • .toPrecision(precision?: number): string ^[ES3]^ 像.toString()一样工作,但在返回结果之前将尾数修剪为数字precision。如果缺少precision,则使用.toString()
    > 1234..toPrecision(3)  // requires exponential notation
    '1.23e+3'
    > 1234..toPrecision(4)
    '1234'
    > 1234..toPrecision(5)
    '1234.0'
    > 1.234.toPrecision(3)
    '1.23'
    
  • .toString(radix=10): string ^[ES1]^ 返回数字的字符串表示形式。 返回基数为 10 的结果:
    > 123.456.toString()
    '123.456'
    
    使用 10 以外的基数返回结果(通过radix指定):
    > 4..toString(2)
    '100'
    > 4.5.toString(2)
    '100.1'
    > 255..toString(16)
    'ff'
    > 255.66796875.toString(16)
    'ff.ab'
    > 1234567890..toString(36)
    'kf12oi'
    
    您可以使用parseInt()将整数结果转换回数字:
    > parseInt('kf12oi', 36)
    1234567890
    

13.13.8 来源

下一节:Math是具有数据属性和处理数字的方法的对象。你可以把它看作一个伪模块。今天,它可能会被创建为一个模块,但它早在模块之前就存在了。