JavaScript 系列二:数据类型 (上)
前言
在开始学习之前,我们想要告诉您的是,本文章是对JavaScript语言知识中"数据类型"部分的总结,如果您已掌握下面知识事项,则可跳过此环节直接进入题目练习
Boolean 类型
null 类型
undefined 类型
Number 类型
如果您对某些部分有些遗忘,👇🏻 已经为您准备好了!
汇总总结
Boolean 类型
Boolean(布尔值) 类型是 ECMAScript 中使用最频繁的类型之一,有两个字面值:true 和 false 。这两个布尔值不同于数值,因此 true 不等于 1, false 不等于 0 。
let xhsFound = true
let xhsLost = false
注意:布尔值字面量 true 和 false 是区分大小写的(即不能使用 False 和 True )。
Boolean() 转型函数
该函数可以将一个其他类型的值转换为布尔值。
let message = 'Hello world!'
let messageAsBoolean = Boolean(message) // true
Boolean() 转型函数可以在任意类型的数据上调用,而且始终返回一个布尔值。什么值能转换为 true 或 false 的规则取决于数据类型和实际的值。
不同类型与布尔值之间的转换规则
数据类型 | 转换为 true 的值 | 转换为 false 的值 |
Boolean | true | false |
String | 非空字符串 | ""(空字符串) |
Number | 非零数值(包括无穷值) | 0、NaN(参见后面的相关内容) |
Object | 任意对象 | null |
Undefined | N/A(不存在) | undefined |
理解以上转换非常重要,因为像 if 等流控制语句会自动执行其他类型值到布尔值的转换,例如:
let message = 'Hello world!'
if (message) {
console.log('Value is true')
}
在这个例子中,console.log 会输出字符串 "Value is true" ,因为字符串 message 会被自动转换为等价的布尔值 true。由于存在这种自动转换,理解控制语句中使用的是什么变量就非常重要。错误地使用对象而不是布尔值会明显改变应用程序的执行逻辑。
null 类型
null 类型同样只有一个值,即特殊值 null 。逻辑上讲,null 值表示一个空对象指针,这也是给 typeof 传一个 null 会返回 "object" 的原因。
let xhsObject = null
console.log(typeof xhsObject) // "object"
在定义将来要保存对象值的变量时,建议使用 null 来初始化,不要使用其他值。这样,只要检查这个变量的值是不是 null 就可以知道这个变量是否在后来被重新赋予了一个对象的引用。
if (xhsObject != null) {
// xhsNull 是一个对象的引用
}
undefined 值是由 null 值派生而来的,因此 ECMA-262 将它们定义为表面上相等
console.log(null == undefined) // true
用等于操作符(==)比较 null 和 undefined 始终返回 true 。但要注意,这个操作符会为了比较而转换它的操作数。
即使 null 和 undefined 有关系,它们的用途也是完全不一样的。永远不必显式地将变量值设置为 undefined 。但 null 不是这样的。任何时候,只要变量要保存对象,
而当时又没有那个对象可保存,就要用 null 来填充该变量。这样就可以保持 null 是空对象指针的语义,并进一步将其与 undefined 区分开来。
null 是一个假值。因此,如果需要,可以用更简洁的方式检测它。不过要记住,也有很多其他可能的值同样是假值。所以一定要明确自己想检测的就是 null 这个字面值,而不仅仅是假值。
let xhsMessage = null
let xhsAge
if (xhsMessage) {
// 这个块不会执行
}
if (!xhsMessage) {
// 这个块会执行
}
if (xhsAge) {
// 这个块不会执行
}
if (!xhsAge) {
// 这个块会执行
}
undefined 类型
undefined 类型只有一个值,就是特殊值 undefined 。当使用 var 或 let 声明了变量但没有初始化时,就相当于给变量赋予了 undefined 值。
let xhsMessage
console.log(xhsMessage == undefined) // true
在这个例子中,变量 xhsMessage 在声明的时候并未初始化。而在比较它和 undefined 的字面值时,两者是相等的。
let xhsMessage = undefined
console.log(xhsMessage == undefined) // true
这里,变量 message 显式地以 undefined 来初始化。但这是不必要的,因为默认情况下,任何未经初始化的变量都会取得 undefined 值。
注意 一般来说,永远不用显式地给某个变量设置 undefined 值。增加这个特殊值的目的就是为了正式明确空对象指针( null )和未初始化变量的区别。
注意,包含 undefined 值的变量跟未定义变量是有区别的。请看下面的例子:
let xhsMessage // 这个变量被声明了,只是值为 undefined
// 确保没有声明过这个变量
// let xhsAge
console.log(xhsMessage) // "undefined"
console.log(xhsAge) // 报错
在上面的例子中,第一个 console.log 会指出变量 message 的值,即 "undefined" 。而第二个 console.log 要输出一个未声明的变量 age 的值,因此会导致报错。对未声明的变量,只能执行一个有用的操作,就是对它调用 typeof 。(对未声明的变量调用 delete 也不会报错,但这个操作没什么用,实际上在严格模式下会抛出错误。)
在对未初始化的变量调用 typeof 时,返回的结果是 "undefined" ,但对未声明的变量调用它时,返回的结果还是 "undefined" ,这就有点让人看不懂了。
let xhsMessage // 这个变量被声明了,只是值为 undefined
// 确保没有声明过这个变量
// let xhsAge
console.log(typeof xhsMessage) // "undefined"
console.log(typeof xhsAge) // "undefined"
无论是声明还是未声明,typeof 返回的都是字符串 "undefined" 。逻辑上讲这是对的,因为虽然严格来讲这两个变量存在根本性差异,但它们都无法执行实际操作。
注意: 即使未初始化的变量会被自动赋予 undefined 值,但我们仍然建议在声明变量的同时进行初始化。这样,当 typeof 返回 "undefined" 时,你就会知道那是因为给定的变量尚未声明,而不是声明了但未初始化。
undefined 是一个假值。因此,如果需要,可以用更简洁的方式检测它。不过要记住,也有很多其他可能的值同样是假值。所以一定要明确自己想检测的就是 undefined 这个字面值,而不仅仅是假值。
let xhsMessage // 这个变量被声明了,只是值为 undefined
// xhsAge 没有声明
if (xhsMessage) {
// 这个块不会执行
}
if (!xhsMessage) {
// 这个块会执行
}
if (xhsAge) {
// 这里会报错
}
Number 类型
Number 类型使用 IEEE 754 格式表示整数和浮点值(在某些语言中也叫双精度值)。
十进制整数
let xhsIntNum = 55 // 整数
整数也可以用八进制(以 8 为基数)或十六进制(以 16 为基数)字面量表示。
八进制整数
对于八进制字面量,第一个数字必须是零(0),然后是相应的八进制数字(数值 0~7)。如果字面量中包含的数字超出了应有的范围,就会忽略前缀的零,后面的数字序列会被当成十进制数。
let xhsOctalNum1 = 070 // 八进制的 56
let xhsOctalNum2 = 079 // 无效的八进制值,当成 79 处理
let xhsOctalNum3 = 08 // 无效的八进制值,当成 8 处理
十六进制整数
要创建十六进制字面量,必须让真正的数值前缀 0x(区分大小写),然后是十六进制数字(0~9 以 及 A~F)。十六进制数字中的字母大小写均可。
let xhsHexNum1 = 0xa // 十六进制 10
let xhsHexNum2 = 0x1f // 十六进制 31
注意
使用八进制和十六进制格式创建的数值在所有数学操作中都被视为十进制数值。
由于 JavaScript 保存数值的方式,实际中可能存在正零( +0 )和负零( -0 )。正零和负零在所有情况下都被认为是等同的,这里特地说明一下。
浮点值
要定义浮点值,数值中必须包含小数点,而且小数点后面必须至少有一个数字。虽然小数点前面不是必须有整数,但推荐加上。
let xhsFloatOne = 1.11111
let xhsFloatTwo = 0.11111
let xhsFloatThree = 0.11111 // 有效,不推荐
因为存储浮点值使用的内存空间是存储整数值的 两倍 ,所以 ECMAScript 总是想方设法把值转换为整数。在小数点后面没有数字的情况下,数值就会变成整数。
let xhsFloatOne = 1 // 小数点后面没有数字,当成整数 1 处理
let xhsFloatTwo = 2.0 // 小数点后面是零,当成整数 2 处理
对于非常大或非常小的数值,浮点值可以用科学记数法来表示。科学记数法用于表示一个应该乘以 10 的给定次幂的数值。ECMAScript 中科学记数法的格式要求是一个数值(整数或浮点数)后跟一个大写或小写的字母 e,再加上一个要乘的 10 的多少次幂。
let xhsFloat = 3.125e4 // 等于 31250
科学记数法也可以用于表示非常小的数值,例如 0.000 000 000 000 000 03。这个数值用科学记数法可以表示为 3e-17。
浮点值的精确度最高可达 17 位小数,但在算术计算中远不如整数精确。例如, 0.1 加 0.2 得到的不是 0.3 。由于这种微小的舍入错误,导致很难测试特定的浮点值。
if (a + b == 0.3) {
//这样判断是错误的
// 0.1 + 0.2 = 0.300 000 000 000 000 04
console.log('输出 0.3 .')
}
这里检测两个数值之和是否等于 0.3。如果两个数值分别是 0.05 和 0.25,或者 0.15 和 0.15 ,那没问题。但如果是 0.1 和 0.2,如前所述,测试将失败。因此永远不要测试某个特定的浮点值。
值的范围
最大和最小值
由于内存的限制, ECMAScript 并不支持表示这个世界上的所有数值。
最 小 数值保存在 Number.MIN_VALUE 中,这个值在多数浏览器中是 5e-324
最 大 数值保存在 Number.MAX_VALUE 中,这个值在多数浏览器中是 1.797 693 134 862 315 7e+308
无穷大和无穷小
如果某个计算得到的数值结果超出了可表示的范围,那么这个数值会被自动转换为一个特殊的 Infinity(无穷)值。
任何无法表示的负数以-Infinity(负无穷大)表示
任何无法表示的正数以 Infinity(正无穷大)表示。
isFinite()函数
用于确认一个值是不是在有限数值范围之内(即最大值和最小值之间),不在 false ,再显示 true
let xhsResult = Number.MAX_VALUE + Number.MAX_VALUE
console.log(isFinite(xhsResult)) // false
注意
如果计算返回正 Infinity 或 负 Infinity,则该值将不能再进一步用于任何计算。这是因为 Infinity 没有可用于计算的数值表示形式。
使用 Number.NEGATIVE_INFINITY 和 Number.POSITIVE_INFINITY 也可以获取正、负 Infinity。没错,这两个属性包含的值分别就是 -Infinity 和 Infinity。
虽然超出有限数值范围的计算并不多见,但总归还是有可能的。因此在计算非常大或非常小的数值时,有必要监测一下计算结果是否超出范围。
NaN
有一个特殊的数值叫 NaN ,意思是“不是数值”( Not a Number ),用于表示本来要返回数值的操作失败了(而不是抛出错误)。比如,用 0 除任意数值在其他语言中通常都会导致错误,从而中止代码执行。但在 ECMAScript 中, 0、 +0 或 -0 相除会返回 NaN
console.log(0 / 0) // NaN
console.log(-0 / +0) // NaN
如果分子是非 0 值,分母是有符号 0 或无符号 0,则会返回 Infinity 或 -Infinity :
console.log(1 / 0) // Infinity
console.log(1 / -0) // -Infinity
NaN 的独特属性
任何涉及 NaN 的操作始终返回 NaN(如 NaN/10),在连续多步计算时这可能是个问题
NaN 不等于包括 NaN 在内的任何值。例如,下面的比较操作会返回 false :
console.log(NaN == NaN) // false
isNaN()函数
该函数接收一个参数,可以是任意数据类型,判断这个参数是不是“不是数值”。该函数会尝试把传入的参数转换为数值。可以转化为数值的则返回 false ,如字符串 "1" 或布尔值。不能转换为数值的值则返回 true .
console.log(isNaN(NaN)) // true
console.log(isNaN(1)) // false,1 是数值
console.log(isNaN('1')) // false,可以转换为数值 1
console.log(isNaN('blue')) // true,不可以转换为数值
console.log(isNaN(true)) // false,可以转换为数值 1
注意: 虽然不常见,但 isNaN() 可以用于测试对象。此时,首先会调用对象的 valueOf() 方法,然后再确定返回的值是否可以转换为数值。如果不能,再调用 toString() 方法,并测试其返回值。