数字和字符串

本章将介绍 JavaScript 中两个最基本的数据类型:数字和字符串。我们将介绍它们的底层表示,以及用于处理和执行计算的函数。

数字

在 JavaScript 中,数字采用双精度 64 位二进制格式 IEEE 754 实现(即,一个介于 ±2^−1022 和 ±2^+1023 之间的数字,或者大约 ±10^−308 到 ±10^+308 之间,数字精度为 53 位)。整数值可精确表示到 ±2^53 − 1。

除了能够表示浮点数之外,数字类型还有三个符号值:Infinity-InfinityNaN(非数字)。

另请参阅 JavaScript 数据类型和结构,以了解 JavaScript 中其他基本类型的上下文。

您可以使用四种类型的数字字面量:十进制、二进制、八进制和十六进制。

十进制数字

js
1234567890
42

十进制字面量可以以零 (0) 开头,后跟另一个十进制数字,但如果前导 0 之后的所有数字都小于 8,则该数字被解释为八进制数字。这被认为是遗留语法,以 0 为前缀的数字字面量,无论是解释为八进制还是十进制,在严格模式下都会导致语法错误——因此,请改用 0o 前缀。

js
0888 // 888 parsed as decimal
0777 // parsed as octal, 511 in decimal

二进制数字

二进制数字语法使用前导零,后跟小写或大写拉丁字母“B”(0b0B)。如果 0b 之后的数字不是 0 或 1,则会抛出以下 SyntaxError:“Missing binary digits after 0b”。

js
0b10000000000000000000000000000000 // 2147483648
0b01111111100000000000000000000000 // 2139095040
0B00000000011111111111111111111111 // 8388607

八进制数字

八进制数字的标准语法是前缀 0o。例如

js
0O755 // 493
0o644 // 420

八进制数字也有一个遗留语法——通过在八进制数字前加一个零:0644 === 420"\045" === "%"。如果 0 之后的数字超出 0 到 7 的范围,则该数字将被解释为十进制数字。

js
const n = 0755; // 493
const m = 0644; // 420

严格模式禁止这种八进制语法。

十六进制数字

十六进制数字语法使用前导零,后跟小写或大写拉丁字母“X”(0x0X)。如果 0x 之后的数字超出范围(0123456789ABCDEF),则会抛出以下 SyntaxError:“Identifier starts immediately after numeric literal”。

js
0xFFFFFFFFFFFFF // 4503599627370495
0xabcdef123456  // 188900967593046
0XA             // 10

幂运算

js
0e-5   // 0
0e+5   // 0
5e1    // 50
175e-2 // 1.75
1e3    // 1000
1e-3   // 0.001
1E3    // 1000

数字分隔符

对于上面显示的所有字面量语法,可以在数字之间插入下划线 (_) 以提高可读性。

js
1_000_000_000_000
1_050.95
0b1010_0001_1000_0101
0o2_2_5_6
0xA0_B0_C0
1_000_000_000_000_000_000_000n

有关数字字面量的更多详细信息,请参阅词法语法参考。

Number 对象

内置的 Number 对象具有数值常数的属性,例如最大值、非数字和无穷大。您无法更改这些属性的值,并且可以按如下方式使用它们

js
const biggestNum = Number.MAX_VALUE;
const smallestNum = Number.MIN_VALUE;
const infiniteNum = Number.POSITIVE_INFINITY;
const negInfiniteNum = Number.NEGATIVE_INFINITY;
const notANum = Number.NaN;

您始终如上所示引用预定义的 Number 对象的属性,而不是您自己创建的 Number 对象的属性。

下表总结了 Number 对象的属性。

属性 描述
Number.MAX_VALUE 最大可表示正数 (1.7976931348623157e+308)
Number.MIN_VALUE 最小可表示正数 (5e-324)
Number.NaN 特殊“非数字”值
Number.NEGATIVE_INFINITY 特殊负无穷大值;溢出时返回
Number.POSITIVE_INFINITY 特殊正无穷大值;溢出时返回
Number.EPSILON 1 与大于 1 且可以表示为 Number 的最小数值之间的差值 (2.220446049250313e-16)
Number.MIN_SAFE_INTEGER JavaScript 中的最小安全整数(−2^53 + 1,或 −9007199254740991
Number.MAX_SAFE_INTEGER JavaScript 中的最大安全整数(+2^53 − 1,或 +9007199254740991
方法 描述
Number.parseFloat() 解析字符串参数并返回浮点数。与全局 parseFloat() 函数相同。
Number.parseInt() 解析字符串参数并返回指定基数或底数的整数。与全局 parseInt() 函数相同。
Number.isFinite() 确定传入的值是否为有限数。
Number.isInteger() 确定传入的值是否为整数。
Number.isNaN() 确定传入的值是否为 NaN。比原始全局 isNaN() 更健壮的版本。
Number.isSafeInteger() 确定提供的值是否为安全整数

Number 原型提供了以各种格式从 Number 对象检索信息的方法。下表总结了 Number.prototype 的方法。

方法 描述
toExponential() 返回一个以指数表示法表示数字的字符串。
toFixed() 返回一个以定点表示法表示数字的字符串。
toPrecision() 返回一个以定点表示法表示数字到指定精度的字符串。

Math 对象

内置的 Math 对象具有数学常量和函数的属性和方法。例如,Math 对象的 PI 属性具有 pi 的值(3.141…),您将在应用程序中如下使用

js
Math.PI;

同样,标准数学函数是 Math 的方法。这些包括三角函数、对数函数、指数函数和其他函数。例如,如果您想使用三角函数正弦,您将编写

js
Math.sin(1.56);

请注意,Math 的所有三角方法都采用弧度作为参数。

下表总结了 Math 对象的方法。

Math 的方法
方法 描述
abs() 绝对值
sin()cos()tan() 标准三角函数;参数以弧度表示。
asin()acos()atan()atan2() 反三角函数;返回弧度值。
sinh()cosh()tanh() 双曲函数;参数以双曲角表示。
asinh()acosh()atanh() 反双曲函数;返回双曲角值。

pow()exp()expm1()log()log10()log1p()log2()

指数和对数函数。
floor()ceil() 返回小于/大于或等于参数的最大/最小整数。
min()max() 返回以逗号分隔的数字列表作为参数的最小值或最大值(分别)。
random() 返回 0 到 1 之间的随机数。
round()fround()trunc() 舍入和截断函数。
sqrt()cbrt()hypot() 平方根、立方根、平方和参数的平方根。
sign() 数字的符号,指示数字是正数、负数还是零。
clz32(),
imul()
32 位二进制表示中前导零的位数。
两个参数的 C 样式的 32 位乘法结果。

与许多其他对象不同,您永远不会创建自己的 Math 对象。您始终使用内置的 Math 对象。

BigInts

数字值的一个缺点是它们只有 64 位。实际上,由于使用 IEEE 754 编码,它们无法准确表示任何大于 Number.MAX_SAFE_INTEGER(即 253 - 1)的整数。为了解决编码二进制数据以及与其他提供宽整数(如 i64(64 位整数)和 i128(128 位整数))的语言进行互操作的需求,JavaScript 还提供了另一种数据类型来表示任意大整数BigInt

BigInt 可以定义为后缀为 n 的整数文字

js
const b1 = 123n;
// Can be arbitrarily large.
const b2 = -1234567890987654321n;

BigInt 也可以使用 BigInt 构造函数从数字值或字符串值构造。

js
const b1 = BigInt(123);
// Using a string prevents loss of precision, since long number
// literals don't represent what they seem like.
const b2 = BigInt("-1234567890987654321");

从概念上讲,BigInt 只是一个任意长的位序列,它编码一个整数。您可以安全地执行任何算术运算而不会丢失精度或溢出/下溢。

js
const integer = 12 ** 34; // 4.9222352429520264e+36; only has limited precision
const bigint = 12n ** 34n; // 4922235242952026704037113243122008064n

与数字相比,BigInt 值在表示大整数时具有更高的精度;但是,它们不能表示浮点数。例如,除法会四舍五入到零

js
const bigintDiv = 5n / 2n; // 2n, because there's no 2.5 in BigInt

Math 函数不能用于 BigInt 值;它们只适用于数字。

选择 BigInt 还是数字取决于您的用例和输入范围。数字的精度应该能够满足大多数日常任务,而 BigInt 最适合处理二进制数据。

有关您可以使用 BigInt 值执行的操作的更多信息,请阅读表达式和运算符部分,或BigInt 参考

字符串

JavaScript 的 String 类型用于表示文本数据。它是一组 16 位无符号整数值(UTF-16 代码单元)的“元素”。字符串中的每个元素都占据字符串中的一个位置。第一个元素位于索引 0,下一个位于索引 1,依此类推。字符串的长度是其中元素的数量。您可以使用字符串字面量或字符串对象创建字符串。

字符串字面量

您可以使用单引号或双引号在源代码中声明字符串

js
'foo'
"bar"

在字符串字面量中,大多数字符都可以按字面量输入。唯一的例外是反斜杠 (\,它开始一个转义序列)、用于包围字符串的引号字符(它终止字符串),以及换行符(如果前面没有反斜杠,则会导致语法错误)。

可以使用转义序列创建更高级的字符串

十六进制转义序列

\x 后面的数字被解释为十六进制数字。

js
"\xA9" // "©"

Unicode 转义序列

Unicode 转义序列要求 \u 后至少有四个十六进制数字。

js
"\u00A9" // "©"

Unicode 代码点转义

使用 Unicode 代码点转义,可以使用十六进制数字转义任何字符,从而可以使用高达 0x10FFFF 的 Unicode 代码点。使用四位 Unicode 转义通常需要单独编写代理对以实现相同的结果。

另请参阅 String.fromCodePoint()String.prototype.codePointAt()

js
"\u{2F804}"

// the same with simple Unicode escapes
"\uD87E\uDC04"

String 对象

您可以直接在字符串值上调用方法

js
console.log("hello".toUpperCase()); // HELLO

String 值上提供了以下方法

处理字符串时,还有两个对象为字符串操作提供重要功能:RegExpIntl。它们分别在正则表达式国际化中介绍。

模板字面量

模板字面量是允许嵌入表达式的字符串字面量。您可以使用它们的多行字符串和字符串插值功能。

模板字面量由反引号(重音符)字符 (`) 包围,而不是双引号或单引号。模板字面量可以包含占位符。这些由美元符号和花括号 (${expression}) 表示。

多行

源代码中插入的任何换行符都是模板字面量的一部分。使用普通字符串,您必须使用以下语法来获取多行字符串

js
console.log(
  "string text line 1\n\
string text line 2",
);
// "string text line 1
// string text line 2"

为了通过多行字符串获得相同的效果,您现在可以编写

js
console.log(`string text line 1
string text line 2`);
// "string text line 1
// string text line 2"

嵌入式表达式

为了在普通字符串中嵌入表达式,您将使用以下语法

js
const five = 5;
const ten = 10;
console.log(
  "Fifteen is " + (five + ten) + " and not " + (2 * five + ten) + ".",
);
// "Fifteen is 15 and not 20."

现在,使用模板字面量,您可以利用语法糖,使此类替换更具可读性

js
const five = 5;
const ten = 10;
console.log(`Fifteen is ${five + ten} and not ${2 * five + ten}.`);
// "Fifteen is 15 and not 20."

有关更多信息,请阅读 JavaScript 参考中的模板字面量