数据类型
2023年2月21日大约 8 分钟
数据类型
- 分类
- 基本数据类型:
Undefined
、Null
、Boolean
、Number
、BigInt
String
、Symbol
- 复杂数据类型:
Object
- 基本数据类型:
Undefined 类型
- Undefined 类型只有一个值,即 undefined
- 使用
var
声明变量但未初始化时,值为 undefined - 对未声明的变量
typeof
时,也会返回 undefined - 相等性检查 == 中,undefined 只与 null 相等
Null 类型
- Null 类型只有一个值,即 null
- 从逻辑角度看,null 表示空对象指针
- console.log(typeof null); // object
- undefined 值派生自 null 值
- console.log(null==undefined); // true
**undefined** 和 **null** 在相等性检查 `==` 中不会进行任何类型转换,除非你非常清楚自己在做什么,否则永远不要使用
>= > < <=
去比较一个可能为 `null/undefined` 的变量。对于取值可能是 `null/undefined` 的变量,请按需要分别检查它的取值情况Boolean 类型
- 该类型只有两个值:
true
、false
,并且区分大小写 - 一个值要转化为 Boolean 值,可以调用 Boolean()
其他类型转化为布尔值的规则
数据类型 | 转化为 true 的值 | 转化为 false 的值 |
---|---|---|
Boolean | true | false |
String | 任何非空字符串 | 空字符串 |
Number | 任何非零数字值(包括无穷大) | 0 和 NaN |
Object | 任何对象 | null |
Undefined | 不存在 | undefined |
Number 类型
- 使用 IEEE754 格式来表示整数和浮点数值(双精度数值)
- 十进制
- 八进制
- 以 8 为基数
- 第一位必须是 0,后面为八进制数字序列(0~7)
- 如果字面值的数值超出范围,则前导 0 被忽略,后面的数被当做十进制数值
- 八进制字面量在严格模式下无效,会报错
- 十六进制
- 以 16 为基数
- 前两位必须是 0x,后面为十六进制数字序列(0-9 及 A~F),不区分大小写
- 在进行算数计算时,所有的八进制和十六进制表示的数值都将被换成十进制数值
- NaN,即非数值,是一个特殊的数值
- 表示一个本来要返回数值的操作数未返回数值的情况(不会抛出错误)
- 任何数值除以 0 都会返回 NaN,不会影响其它代码执行
- 任何涉及 NaN 的操作(例如 NaN/10)都会返回 NaN
- NaN 与任何值都不相等,包括其本身
- console.log(NaN==Nan); // false
- isNaN() 接受一个任意类型参数,判断这个参数是否 “不是数值”(尝试转化为数值),并返回布尔值
- 不能被转化为数值的值返回 true
- 能转化为数值的值返回 false
- 注意:
- 浮点数精度问题
- 0.1+0.2=0.30000000000000004(不要测试某个特定的浮点数值)
- 数值范围
- 最小数值 Number.MIN_VALUE,大多数浏览器中,这个值是 5e-324
- 最大数值 Number.MAX_VALUE,大多数浏览器中,这个值是 1.7976931348623157e+308
- 如果计算超出了这个数值范围,这个数值将被自动转换成特殊的 Infinity 值
- -Infinity 负无穷
- Infinity 正无穷
- 浮点数精度问题
- 三个将非数值转化为数值的函数:Number()、parseInt()、parseFloat()
Number() 函数转换规则
- 如果是布尔值,true 和 false 将分别被转换为 1 和 0
- 如果是数字值,只是简单的传入和返回
- 如果是 null 值,返回 0
- 如果是 undefined ,返回 NaN
- 如果是字符串,遵循下列规则
- 如果字符串中只包含数字(包括前面带正号或符号的情况),则将其转换为十进制数值(会忽略前导 0)
- 如果字符串包含有效的浮点格式,则将其转换为对应的浮点数值(会忽略前导 0)
- 如果字符串包含有效的十六进制格式,则将其转换为对应的十进制整数值
- 如果字符串是空的(不包含任何字符),则将其转换为 0
- 如果字符串包含上述格式以外的字符,则将其转换为 NaN
- 如果是对象,则调用对象的 valueOf() 方法,然后依照前面的规则转换反悔的值。如果转换的结果是 NaN,则调用对象的 toString() 方法,然后再次依照前面的规则转换反悔的字符串值
- 一元加操作符的操作与 Number() 函数相同
parseInt() 函数转换规则
- 空字符串,返回 NaN
- 忽略字符串前的空格,直至找到第一个非空字符串
- 如果第一个字符不是数字或者正负号,返回 NaN
- 如果第一个字符是数字字符,则会继续解析后续字符直至遇到一个非数字字符
- 遇到小数点也会停止,因为小数点不是有效的数字字符
- 能识别出其他进制数字字符,转化为十进制返回
- 八进制的字面量字符串存在分歧,可以携带第二个参数,表示转化是使用的基数(即进制)
- console.log(parseInt("0xAF",16)); // 175 (可以省略 0x)
parseFloat() 函数转换规则
- parseFloat() 与 parseInt() 函数类似
- 解析过程成遇到的第一个小数点有效,第二个小数点无效
- 只解析十进制,没有第二个参数
- 十六进制字符串始终会被转换成 0
- 如果字符串包含的是一个可解析为整数的数(没有小数点,或小数点后面都是 0),则函数会返回整数
String 类型
- 两个将一个值转化为一个字符串的函数:toString()、String()
toString() 函数转换规则
- 数值、布尔值、对象和字符串都有 toString() 方法,该方法返回字符串的一个副本
- null 和 undefined 值没有这个方法
- 多数情况下,toString() 方法不用传递参数
- 调用数值的 toString() 方法时,可以传递一个参数,表示输出数值的基数(进制,默认为 10)
String() 函数转换规则
- 在不知道要转换的值是不是 null 或 undefined 的情况下可以使用,可以将任何类型的值转换为字符串
- 如果值有 toString() 方法,则调用该方法(没有参数)并返回相应结果
- 如果值是 null ,则返回 “null”
- 如果值是 undefined ,则返回 “unfined”
Object 类型
- 一组数据和功能的集合
- Object 类型所具有的任何属性和方法也同样存在于更具体的对象中
Object 的每个实例都具有以下属性和方法
- Constructor:保存着用于创建当前对象的函数
- hasOwnProperty(propertyName):用于检查给定的属性在当前对象实例中(而不是在实例的原型中)是否存在
- 作为参数的属性名(propertyName)必须以字符串形式指定
- 例如:o.hasOwnProperty("name")
- 作为参数的属性名(propertyName)必须以字符串形式指定
- isPrototypeOf(object):用于检查传入的对象是否是另一个对象的原型
- propertyIsEnumerable(propertyName):用于检查给定的属性是否能够使用 for-in 语句来枚举。
- 作为参数的属性名(propertyName)必须以字符串形式指定
- toLocaleString():返回对象的字符串表示,该字符串与执行环境的地区对应
- toString():返回对象的字符串表示
- valueOf():返回对象的字符串、数值或布尔值表示。通常与 toString() 方法的返回值相同
类型判断
typeof 操作符
是确定一个变量是 字符串、数值、布尔值还是 undefined 的最佳工具
如果值是一个对象或 null ,结果返回 object
如果值是函数,该操作符会返回 function
如果值是正则表达式,则可能返回 function 或 object (浏览器差异)
- 语法:
typeof x
或typeof(x)
- 返回变量数据类型的字符串,返回结果如下
undefined
:值 未定义boolean
:值为 布尔值string
:值为 字符串number
:值为 数值bigint
:值为特大的数值object
:值为 对象或 nullfunction
:值为 函数symbol
:值位 symbol
instanceof 操作符
- 语法:
result = variable instanceof constructor
- 如果变量是给定引用类型(根据原型链识别)的实例则返回 true
- 所有引用类型都是
Object
的实例,在检测一个应用类型值和Object
构造函数时,instanceof
操作符始终会返回true
- 如果使用
instanceof
操作符检测基本数据类型的值,该操作符始终返回false
,因为基本类型不是对象
- 所有引用类型都是
比 typeof 运算符更准确的类型判断
不同数据类型的Object.prototype.toString
方法返回值如下。
- 数值:返回
[object Number]
。 - 字符串:返回
[object String]
。 - 布尔值:返回
[object Boolean]
。 - undefined:返回
[object Undefined]
。 - null:返回
[object Null]
。 - 数组:返回
[object Array]
。 - arguments 对象:返回
[object Arguments]
。 - 函数:返回
[object Function]
。 - Error 对象:返回
[object Error]
。 - Date 对象:返回
[object Date]
。 - RegExp 对象:返回
[object RegExp]
。 - 其他对象:返回
[object Object]
。
这就是说,Object.prototype.toString
可以看出一个值到底是什么类型。
Object.prototype.toString.call(2) // "[object Number]"
Object.prototype.toString.call('') // "[object String]"
Object.prototype.toString.call(true) // "[object Boolean]"
Object.prototype.toString.call(undefined) // "[object Undefined]"
Object.prototype.toString.call(null) // "[object Null]"
Object.prototype.toString.call(Math) // "[object Math]"
Object.prototype.toString.call({}) // "[object Object]"
Object.prototype.toString.call([]) // "[object Array]"
利用这个特性,可以写出一个比typeof
运算符更准确的类型判断函数。
var type = function (o) {
var s = Object.prototype.toString.call(o)
return s.match(/\[object (.*?)\]/)[1].toLowerCase()
}
type({}) // "object"
type([]) // "array"
type(5) // "number"
type(null) // "null"
type() // "undefined"
type(/abcd/) // "regex"
type(new Date()) // "date"
在上面这个type
函数的基础上,还可以加上专门判断某种类型数据的方法。
var type = function (o) {
var s = Object.prototype.toString.call(o)
return s.match(/\[object (.*?)\]/)[1].toLowerCase()
}
;[
'Null',
'Undefined',
'Object',
'Array',
'String',
'Number',
'Boolean',
'Function',
'RegExp'
].forEach(function (t) {
type['is' + t] = function (o) {
return type(o) === t.toLowerCase()
}
})
type.isObject({}) // true
type.isNumber(NaN) // true
type.isRegExp(/abc/) // true