JavaScript数据类型
本文最后更新于 2025年7月30日 下午
ECMAScript 目前有数据类型:Undefined、Null、Boolean、Number、String、Symbol、BigInt、Object。
前 7 种为简单数据类型(也称基本类型、基本值),最后 1 种为复杂数据类型(也称引用类型、引用值)。
在 ECMAScript 中不能定义自己的数据类型,所有值都可以用上述数据类型之一来表示。只有 8 种数据类型似乎不足以表示全部数据。但 ECMAScript 数据类型很灵活,一种数据类型可以当作多种数据类型来使用。
Undefined 类型
Undefined 类型只有一个值:特殊值 undefined
。
当使用 var 或 let 声明了、但是没有初始化的变量时,就相当于给变量赋予了 undefined 值。一般来说,永远不用显式地给某个变量设 undefined 值。因为在默认情况下,任何未经初始化的变量的值都是 undefined 。undefined 值主要用于比较,增加这个特殊值就是为了正式明确空对象指针(null)和未初始化变量的区别。
无论是声明了、但是没有初始化的变量还是未声明的变量,对其使用 typeof 返回的都是字符串”undefined”。逻辑上讲这是对的,因为虽然严格来讲这两个变量存在根本性差异,但它们都无法执行实际操作。
需要注意,声明了、但是没有初始化的变量和未声明的变量还是有区别的。声明了、但是没有初始化的 undefined 值变量可以被打印,未声明定义的变量打印会报错。
1 |
|
Null 类型
Null 类型只有一个值:特殊值 null
。
逻辑上讲,null 值表示一个空对象指针,这也是给 typeof 传 null 值返回”object”的原因。
undefined 值是由 null 值派生而来的,因此 ECMA-262 将它们定义为表面上相等。用等于操作符(==)比较 null 和 undefined 返回 true,用全等操作符(===)比较 null 和 undefined 返回 false。
即使 null 和 undefined 有关系,它们的用途也是完全不一样的。如前所述,永远不必显式地将变量值设置为 undefined。但 null 不是这样的。任何时候,只要变量要保存对象,而当时又没有那个对象可保存,就要用 null 来填充该变量。这样就可以保持 null 是空对象指针的语义,并进一步将其与 undefined 区分开来。
Boolean 类型
Boolean 类型有两个字面值:true
和 false
。
这两个布尔值不同于数值, true 不等于 1,false 不等于 0。布尔值字面量 true 和 false 都是区分大小写的,因此 True 和 False 之类是有效的标识符,但不是布尔值。
虽然布尔值只有两个,但所有其他 ECMAScript 类型的值都有相应布尔值的等价形式。要将一个其他类型值转换为布尔值,可以调用特定的Boolean()
转型函数(将要转型的值作为参数传入)。Boolean()
转型函数可以在任意类型的数据上调用,而且始终返回一个布尔值。
下表总结了不同类型与布尔值之间的转换规则:
数据类型 | 转换为 true 的值 | 转换为 false 的值 |
---|---|---|
Undefined | 无 | undfined |
Null | 无 | null |
String | 非空字符串 | 空字符串 |
Nmuber | 非零数值 | 0 、NaN |
Symbol | 任意值 | 无 |
BigInt | 任意值 | 无 |
Object | 任意值 | 无 |
Number 类型
Number 类型使用 IEEE 754 格式表示整数和浮点值(在某些语言中也叫双精度值)。不同的数值类型相应地也有不同的数值字面量格式。
最基本的数值字面量格式是十进制整数,直接写出来即可。整数也可以用八进制或者十六进制字面量表示。但是,使用八进制和十六进制格式创建的数值在所有数学操作中都被视为十进制数值。
- 八进制字面量,第一个数字必须是零(0),然后是八进制数字(数值 0~7)。
如果字面量中包含的数字超出了应有的范围,就会忽略前缀的零,后面的数字序列会被当成十进制数。 - 十六进制字面量,必须让真正的数值前缀 0x(区分大小写),然后是十六进制数字(0~9 及 A~F)。
十六进制数字中的字母大小写均可。
正零(+0)和负零(-0)在所有情况下都被认为是等同的,除了使用 Object.is() 方法时。
浮点数
要定义浮点值,数值中必须包含小数点,而且小数点后面必须至少含有一个非零数字。虽然小数点前面不是必须有整数,但推荐加上。
因为存储浮点值使用的内存空间是存储整数值的两倍,所以 ECMAScript 总是想方设法把值转换为整数。在小数点后面没有数字的情况下,数值就会变成整数。类似地,如果数值本身就是整数,只是小数点后面跟着 0(如 1.0),那它也会被转换为整数。
对于非常大或非常小的数值,浮点值可以用科学记数法来表示。科学记数法用于表示一个应该乘以 10 的给定次幂的数值。在 ECMAScript 中,科学记数法的格式要求是一个数值(整数或浮点数)后跟一个大写或小写字母 e,再加上一个要乘的 10 的多少次幂。对非常小的数值,默认情况下,ECMAScript 会将小数点后至少包含 6 个零的浮点值转换为科学记数法。
浮点值的精确度最高可达 17 位小数,但在算术计算中远不如整数精确。因为使用了 IEEE 754 数值,所以存在舍入错误,因此永远不要测试某个特定的浮点值。
值的范围
由于内存的限制,ECMAScript 不支持表示这个世界上的所有数值。ECMAScript 可以表示的最小数值保存在 Number.MIN_VALUE 中,这个值在多数浏览器中是 5e-324;可以表示的最大数值保存在 Number.MAX_VALUE 中,这个值在多数浏览器中是 1.7976931348623157e+308。
如果某个计算得到的数值结果超出了 JavaScript 可以表示的范围,那么这个数值会被自动转换为一个特殊的 Infinity(无穷)值。任何无法表示的负数以-Infinity 表示,任何无法表示的正数以 Infinity 表示。
如果计算返回 +Infinity 或 -Infinity,则该值将不能再进一步用于任何计算。这是因为 Infinity 没有可用于计算的数值表示形式。若要确定一个值是不是有限大(即介于 JavaScript 能表示的最小值和最大值之间),可以使用 isFinite()
函数(将要检测的值作为参数传入)。
NaN
有一个特殊的数值叫 NaN,意思是“不是数值”(Not a Number),用于表示本来要返回数值的操作失败了(而不是抛出错误)。比如,用 0 除任意数值在其他语言中通常都会导致错误,从而中止代码执行。但在 ECMAScript 中,0、+0 或 -0 相除会返回 NaN,如果分子是非 0 值,分母是有符号或无符号 0,则会返回 Infinity 或-Infinity。
NaN 有几个独特的属性:
- 任何涉及 NaN 的操作始终返回 NaN
- NaN 不等于包括 NaN 在内的任何值
- ECMAScript 提供
isNaN()
函数(将要检测的值作为参数传入)。参数可以是任意数据类型,然后判断这个参数是否“不是数值”。把一个值传给isNaN()
函数后,该函数会尝试把它转换为数值。某些非数值的值可以直接转换成数值,任何不能转换为数值的值都会导致这个函数返回 true。
虽然不常见,但 isNaN() 函数可以用于测试对象。此时,首先会调用对象的 valueOf() 方法,然后再确定返回的值是否可以转换为数值。如果不能,再调用 toString() 方法,并测试其返回值。这通常是 ECMAScript 内置函数和操作符的工作方式。
数值转换
有 3 个函数可以将非数值转换为数值: Number()
、 parseInt()
和 parseFloat()
。
String 类型
String 类型表示零或多个 16 位 Unicode 字符序列。字符串可以使用双引号(”)、单引号(’)或反引号(`)来标示。跟某些语言中使用不同的引号会改变对字符串的解释方式不同,ECMAScript 语法中表示字符串的引号没有区别。不过要注意的是,以某种引号作为字符串开头,必须仍然以该种引号作为字符串结尾。
Symbol 类型
Symbol 类型是 ECMAScript 6 新增的数据类型。符号是原始值,且符号实例是唯一、不可变的。符号的用途是确保对象属性使用唯一标识符,不会发生属性冲突的危险。
尽管听起来跟私有属性有点类似,但符号并不是为了提供私有属性的行为才增加的(尤其是因为 Object API 提供了方法,可以更方便地发现符号属性)。相反,符号就是用来创建唯一记号,进而用作非字符串形式的对象属性。
BigInt 类型
Object 类型
ECMAScript 中的对象其实就是一组数据和功能的集合。对象通过 new 操作符后跟对象类型的名称来创建。开发者可以通过创建 Object 类型的实例来创建自己的对象,然后再给对象添加属性和方法。
ECMAScript 只要求在给构造函数提供参数时使用括号。如果没有参数,那么完全可以省略括号(不推荐)。
Object 的实例本身并不是很有用,但理解与它相关的概念非常重要。ECMAScript 中的 Object 也是派生其他对象的基类。Object 类型的所有属性和方法在派生的对象上同样存在。
每个 Object 实例都有如下属性和方法:
- constructor:用于创建当前对象的函数。在前面的例子中,这个属性的值就是 Object() 函数。
- hasOwnProperty(propertyName):用于判断当前对象实例(不是原型)上是否存在给定的属性。要检查的属性名必须是字符串(如 o.hasOwnProperty(“name”))或符号。
- isPrototypeOf(object):用于判断当前对象是否为另一个对象的原型。
- propertyIsEnumerable(propertyName):用于判断给定的属性是否可以使用 for-in 语句枚举。与 hasOwnProperty() 一样,属性名必须是字符串。
- toLocaleString():返回对象的字符串表示,该字符串反映对象所在的本地化执行环境。
- toString():返回对象的字符串表示。
- valueOf():返回对象对应的字符串、数值或布尔值表示。通常与 toString()的返回值相同。
typeof 操作符
因为 ECMAScript 的类型系统是松散的,所以需要一种手段来确定任意变量的数据类型,typeof
操作符就是为此而生的。对一个值使用 typeof 操作符会返回下列字符串之一
字符串 | 表示值 |
---|---|
“undefined” | 未定义 |
“boolean” | 布尔值 |
“number” | 数值 |
“string” | 字符串 |
“symbol” | 符号 |
“bigint” | 任意大的整数 |
“object” | 对象或 null |
“function” | 函数 |
typeof 在某些情况下返回的结果可能会让人费解,但技术上讲还是正确的。如:
- 对 null 使用 typeof 会返回”object”。这是因为,null 表示一个对空对象的引用。
- 对函数使用 typeof 会返回”function”。这是因为,虽然函数被认为是可执行的 Object 类型变量,不代表一种数据类型,但函数有自己特殊的属性。为此,就有必要通过 typeof 操作符来区分函数和其他对象。
示例
1 |
|