菜单

原始值

相关源文件

本文档提供了对 JavaScript 原始值类型的详细概述:它们的特性、行为以及与对象的区别。它涵盖了七种内置的原始类型,以及它们如何作为 JavaScript 语言的基础构建块。有关对象值的信息,请参阅 对象值,有关原始值行为(如不变性和赋值语义)的详细信息,请参阅 原始值行为

JavaScript 中的值类型

JavaScript 不为变量或属性(我们可能称之为“容器类型”)应用类型,而是值本身具有类型——我们可以称之为“值类型”。JavaScript 提供了七种内置的原始(非对象)值类型。

  • undefined - 表示无意中缺失值
  • null - 表示有意缺失值
  • boolean - 表示逻辑上的真/假
  • number - 表示数值(IEEE-754 浮点数)
  • bigint - 表示任意精度的整数
  • symbol - 表示唯一标识符
  • string - 表示文本数据

这些值类型定义了一个或多个具体值的集合,每个类型的值都具有对该类型所有值共享的行为。

来源: types-grammar/ch1.md12-26

原始类型分类

来源: types-grammar/ch1.md16-24

Type-Of 运算符

可以使用 typeof 运算符来检查任何值的类型,该运算符始终返回一个字符串值,表示底层的 JavaScript 值类型。

typeof 用于变量时,它会报告变量中值的类型。

JavaScript 变量本身没有类型。它们可以存储任何任意值,而值本身具有类型。

有一个值得注意的不一致之处:typeof null 返回 "object" 而不是 "null"。这是一个 JavaScript 中的历史遗留 bug,由于向后兼容性问题无法修复。

来源: types-grammar/ch1.md28-50 types-grammar/ch1.md97-103

原始值与对象

是什么具体区分了这 7 种原始值类型与对象类型?原始值是不允许拥有属性的值;只有对象才允许具备此类特性。

在严格模式下,尝试为原始值设置属性会抛出错误。

这种区别可能看起来与诸如 "hello".length 这样的表达式相矛盾,即使在严格模式下,它也返回预期的值 5。这种行为是由“自动装箱”(在需要时自动将原始值包装成临时对象)解释的,我们将在稍后的章节中更详细地探讨。

来源: types-grammar/ch1.md51-92

原始值与对象区分

来源: types-grammar/ch1.md51-92 types-grammar/ch2.md15-57

空值

nullundefined 类型都通常表示空或缺少值。

undefined 类型

undefined 类型既用于显式的 undefined 值,也用于任何遇到看似缺失值的地方。

typeof nonExistent 表达式返回 "undefined",因为 typeof 运算符具有特殊能力,可以安全地访问甚至不存在的标识符而不会引发异常。

来源: types-grammar/ch1.md104-126

null 类型

null 类型具有意外的 typeof 结果。

这并不意味着 null 是一种特殊的对象。这只是 JavaScript 早期的一个遗留问题,由于会破坏现有代码而无法更改。

来源: types-grammar/ch1.md97-103

Nullish 值

从语义上讲,nullundefined 类型都表示一般的空值,或缺少另一个肯定的、有意义的值。在 JavaScript 中,无论遇到的是 null 还是 undefined 都会表现相同的操作,这些操作被称为“nullish”(或“空值类”)。

对于许多 JavaScript 代码而言,这两个空值是可以互换的;在任何给定场景下,有意使用/分配 nullundefined 的决定取决于具体情况,并留给开发者自行决定。

JavaScript 提供了几种将这两种空值视为无法区分的功能。

  1. == 运算符将 nullundefined 视为相等(但不对其他值相等)。
  1. ??(空值合并)运算符
  1. ?.(空值链式调用)运算符

尽管有这些将它们视为相似的功能,但请记住 nullundefined 是不同的类型,并且在某些情况下它们会触发不同的行为。

在此示例中,参数默认值仅对 undefined 生效,而对 null 不生效。

来源: types-grammar/ch1.md127-229

布尔值

boolean 类型包含两个值:falsetrue

在旧的编程语言中,0 通常代表 false,而 1 代表 trueboolean 类型和关键字可以被认为是这些值之上的语义方便的语法糖。

布尔值是 JavaScript 程序中所有决策制定的方式。

! 运算符会否定/翻转布尔值:false 变为 true,而 true 变为 false

来源: types-grammar/ch1.md230-258

字符串值

string 类型包含任何由引号字符分隔的、一个或多个字符的集合。

JavaScript 不区分单个字符作为不同的类型;"a""abc" 一样,都是字符串。

字符串可以由以下方式分隔:

  • 双引号("
  • 单引号('
  • 反引号(`

结束分隔符必须始终与开始分隔符匹配。

来源: types-grammar/ch1.md259-272

字符串长度和字符编码

字符串具有内在长度,该长度对应于它们包含的代码单元(JavaScript 实现中为 16 位单位)。这并不一定对应于可见字符的数量。

JavaScript 使用 UTF-16 进行字符编码,这意味着:

  • 基本多语言平面(BMP)中的字符由一个 16 位代码单元表示。
  • 补充平面中的字符需要两个 16 位代码单元(代理对)。

例如,Unicode 代码点 127878(十六进制 1F386)是 🎆(烟花符号)。JavaScript 在字符串中将其存储为两个代理半代码单元:U+D83CU+DF86

这对字符串长度有影响,因为像 🎆 烟花符号这样的单个可见字符,在计算字符串长度时被计为 2 个字符。

字符类型示例视觉长度JavaScript 长度
BMP 字符"a"11
非 BMP 字符"🎆"12
组合字符"é"12
字位簇"👩‍👩‍👦‍👦"17

来源: types-grammar/ch1.md273-307 types-grammar/ch2.md76-103

Unicode 规范化

Unicode 字符串处理中的另一个复杂性是,即使某些单个 BMP 字符也可以用不同的方式表示。例如,“é”字符可以表示:

  1. 作为字符本身(代码点 233\u00e9)——组合形式
  2. 作为“e”(代码点 101)和组合波浪线(代码点 769)的组合——分解形式

JavaScript 提供了 normalize() 方法来帮助处理这个问题

“NFC” 规范化模式将相邻的代码点组合成复合代码点,而“NFD”规范化模式将单个代码点拆分成其分解代码点。

来源: types-grammar/ch1.md423-476

字符访问和迭代

虽然字符串不是数组,但 JavaScript 允许通过数字索引访问字符

字符串也是可迭代的,这意味着字符可以被单独迭代

此功能源于字符串在 Symbol.iterator 属性上有一个内置的迭代器。

来源: types-grammar/ch2.md136-192

字符串转义序列

JavaScript 字符串可以包含各种字符转义序列

转义序列描述
\b退格符
\f换页符
\n换行符
\r回车符
\tTab键
\v垂直制表符
\0空字符
\'单引号
\"双引号
\\反斜杠
\xXX十六进制转义(XX = 2 个十六进制数字)
\uXXXXUnicode 转义(XXXX = 4 个十六进制数字)
\u{X...}Unicode 代码点转义(X... = 1 个或多个十六进制数字)

示例

来源: types-grammar/ch1.md308-398

模板字面量

字符串也可以使用反引号创建的模板字面量来创建

模板字面量有三个关键特性

  1. 表达式插值(使用 ${...}
  2. 无需转义序列的多行字符串
  3. 标签模板(一项更高级的特性)

来源: types-grammar/ch1.md497-559

数值

number 类型包含任何数值(整数或小数),例如 -423.1415926。这些值由 JavaScript 引擎表示为 64 位、IEEE-754 双精度二进制浮点值。

JavaScript 的 number 始终是小数;整数并不是以不同的方式存储的。“整数”存储为 number 值仅仅是因为其小数部分没有非零值;4242.0 无法区分。

来源: types-grammar/ch1.md562-577

数字表示法

数字可以用不同的基数表示

也支持科学计数法

数字还可以使用下划线作为数字分隔符

来源: types-grammar/ch1.md629-728

解析与强制转换

在将字符串值转换为数字时,区分解析和强制转换很重要

解析(使用 parseInt()parseFloat()

  • 从左到右逐个字符进行处理
  • 遇到非数字字符时停止
  • 如果第一个字符是非数字字符,则返回 NaN

强制转换(使用 Number() 或一元 +

  • 全有或全无的操作
  • 整个字符串必须是数字(整数或浮点数)
  • 如果任何部分是非数字,则结果为 NaN

来源: types-grammar/ch1.md578-627

BigInt 值

JavaScript 中添加了 bigint 类型来表示任意精度的整数。BigInt 字面量通过在数字字面量后附加 n 来创建

BigInt 值可以表示任意大小的整数,而没有 number 类型的精度限制。它们对于会因表示为常规数字而损失精度的非常大的整数特别有用。

BigInts 无论大小都能保持精度,但它们只能表示整数(没有小数)。

来源: types-grammar/toc.md17

Symbol 值

symbol 类型表示唯一、不可变的值,可用作对象属性键以避免名称冲突。Symbol 使用 Symbol() 函数创建

即使具有相同描述的 Symbol 彼此也是唯一的。描述仅用于调试目的,不影响 Symbol 的身份。

JavaScript 还有“众所周知的 Symbol”,例如 Symbol.iterator,它们被用作具有预定义语义含义的特殊属性键。

来源: types-grammar/toc.md18

类型强制转换基础

JavaScript 的原始值可以通过称为强制转换的过程从一种类型转换为另一种类型。类型强制转换可以是显式的(在代码中清晰可见)或隐式的(在后台发生)。

来源: types-grammar/ch4.md12-40 types-grammar/ch4.md400-494

ToBoolean 强制转换

当需要将非布尔值转换为布尔值时(例如在 if 语句条件中),JavaScript 会使用这些规则

假值(Falsy Values)

以下值会转换为 false

  • 未定义
  • null
  • "" (空字符串)
  • 0(零)
  • -0(负零)
  • 0n(BigInt 零)
  • NaN

真值(Truthy Values)

所有其他值都会转换为 true,包括

  • "0"(包含零的字符串)
  • "false"(包含“false”的字符串)
  • [](空数组)
  • {}(空对象)
  • 函数

为了正确处理 JavaScript 中的条件语句,理解这种行为至关重要。

来源: types-grammar/ch4.md48-87

总结

JavaScript 的原始值构成了语言类型系统的基础。这七种原始类型(undefinednullbooleannumberbigintsymbolstring)具有独特的特征,使它们与对象值区分开来

  1. 它们是不可变的
  2. 它们不能附加属性
  3. 它们是按值传递的,而不是按引用传递的
  4. 它们各自具有独特的行为和方法

理解原始值的性质和行为对于编写可靠的 JavaScript 代码至关重要,尤其是在处理类型强制转换、比较以及在 Unicode 世界中处理字符串的细微复杂性时。

来源: types-grammar/ch1.md8-26 types-grammar/ch2.md15-57