最新的 ECMAScript 标准定义了 8 种数据类型:
类型 | 类型名 | 说明 | typeof |
---|---|---|---|
原始值(原始类型) | bigInt |
任意大的整数 | bigInt |
boolean |
布尔值 | boolean | |
null |
空值 | object | |
number |
数值 | number | |
string |
字符串 | string | |
symbol |
符号 | symbol | |
undefined |
未赋值 | undefined | |
对象(引用类型) | object |
对象 | object |
原始值(原始类型)一般具有占据空间小、大小固定的特点,它们存储在栈 stack
中。而引用类型一般是占据空间大、大小不固定,所以存储在堆 heap
中。但引用类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。
undefined
未定义类型。一个没有被赋值的变量/常量会有个默认值 undefined
。
const a
console.log(typeof a) // undefined
console.log(Object.prototype.toString.call(a)) // [object Undefined]
boolean
布尔类型。有两个值 true
和 false
。
const a = true
console.log(typeof a) // boolean
console.log(Object.prototype.toString.call(a)) // [object Boolean]
将其他类型转换为 boolean
的方法:
Boolean(1) // true
Boolean(0) // false
Boolean(NaN) // false
Boolean(undefined) // false
Boolean(null) // false
Boolean('') // false
Boolean(' ') // true
Boolean('Hello') // true
Boolean({}) // true
Boolean([]) // true
!!1 // true
!!0 // false
!!NaN // false
!!undefined // false
!!null // false
!!'' // false
!!' ' // true
!!'Hello' // true
!!{} // true
!![] // true
number
数字类型。
const a = 1
console.log(typeof a) // number
console.log(Object.prototype.toString.call(a)) // [object Number]
将其他类型转换为 number
的方法:
Number(true) // 1
Number(false) // 0
Number('1') // 1
Number('0') // 0
Number(null) // 0
Number('') // 0
Number(' ') // 0
Number([]) // 0
// +"1" // 1
// -"1" // -1
// +null // 0
// -null // -0
// +true // 1
// -true // -1
// +false // 0
arseInt('1.1') // 1
parseFloat('1.1') // 1.1
Math.floor('1.1') // 1
Math.ceil('1.1') // 2
Math.round('1.1') // 1
string
字符串类型。用于表示文本数据。
const a = 'Hello'
console.log(typeof a) // string
console.log(Object.prototype.toString.call(a)) // [object String]
将其他类型转换为 string
的方法:
String(123) // "123"
String(false) // "false"
String(true) // "true"
String(null) // "null"
String(undefined) // "undefined"
String(NaN) // "NaN"
String([1, 2, 3, 4]) // "1,2,3,4"
// 123 + "" // "123"
// (123).toFixed() // "123"
// (123).toString() // "123"
false.toString() // "false"
true.toString() // "true"
JSON.stringify({ a: 1 }) // "{"a":1}"
null
空类型。只有一个值 null
。
判断一个值是否为 null
可以使用全等号 ===
判断是否返回 true
,而不能使用 typeof
判断,因为typeof null
会返回 object
。
这是因为在 JavaScript 最初的实现中,JavaScript 中的值是由一个表示类型的标签和实际数据值表示的。对象的类型标签是 0。由于 null 代表的是空指针(大多数平台下值为 0x00),因此,null 的类型标签是 0,因此 typeof null
返回 object
。
const a = null
console.log(a === null) // true
console.log(typeof null) // object
console.log(Object.prototype.toString.call(a)) // [object Null]
bigInt
数值类型。ES2020 新增,可以表示任意大的整数。
const a = BigInt(123)
console.log(typeof a) // bigint
console.log(Object.prototype.toString.call(a)) // [object BigInt]
symbol
符号类型。ES2015 新增,表示独一无二的值。
const a = Symbol('Hello')
console.log(typeof a) // symbol
console.log(Object.prototype.toString.call(a)) // [object Symbol]
object
对象类型。几乎所有通过 new
创建的对象都属于 object
对象类型。比如:
const a = {} // 等价于 const a = new Object()
console.log(typeof a) // object
console.log(Object.prototype.toString.call(a)) // [object Object]
const b = [] // 等价于 const b = new Array()
console.log(typeof b) // object
console.log(Object.prototype.toString.call(b)) // [object Array]
const c = new Date()
console.log(typeof c) // object
console.log(Object.prototype.toString.call(c)) // [object Date]
const d = new RegExp()
console.log(typeof d) // object
console.log(Object.prototype.toString.call(d)) // [object RegExp]
const e = new Map()
console.log(typeof e) // object
console.log(Object.prototype.toString.call(e)) // [object Map]
const f = new Set()
console.log(typeof f) // object
console.log(Object.prototype.toString.call(f)) // [object Set]
获取数据的具体类型
在判断数据类型时,我们可能首先会想到 typeof
操作符,但是由于 typeof
会把 array
和 object
甚至 null
统一返回 object
类型。所以这里我们需要结合另外一个方法—— Object.prototype.toString().call()
。
该方法的原理是使用对象 Object
原型上的 toString()
方法将该对象转换为字符串,比如 "[object Object]",其中 Object
就是对象的具体类型。最后再使用 call()
改变 this
指向,从而获取我们想要的对象的原型类型。
// boolean
console.log(Object.prototype.toString.call(false)) // [object Boolean]
// number
console.log(Object.prototype.toString.call(1)) // [object Number]
// string
console.log(Object.prototype.toString.call('Hello wolrd!')) // [object String]
// bigint
console.log(Object.prototype.toString.call(10n)) // [object BigInt]
// symbol
console.log(Object.prototype.toString.call(Symbol())) // [object Symbol]
// null
console.log(Object.prototype.toString.call(null)) // [object Null]
// array
console.log(Object.prototype.toString.call([])) // [object Array]
// object
console.log(Object.prototype.toString.call({})) // [object Object]
// function
console.log(Object.prototype.toString.call(function () {})) // [object Function]
最后我们封装一个函数,使用 typeof
结合 Object.prototype.toString.call()
,用于获取数据的具体类型。
function getType(value) {
// 获取数据的 typeof 返回值
let type = typeof value
// 判断是否为 object,如果不是,说明是原始类型,直接返回 typeof 值即可
if (type !== 'object') return type
// 如果是,在获取其具体类型,并提取字符串,转换为小写
return Object.prototype.toString
.call(value)
.replace(/^\[object (\S+)\]$/, '$1')
.toLowerCase()
}
// 测试
console.log(getType(1)) // number
console.log(getType({})) // object
console.log(getType(() => {})) // function
console.log(getType(Symbol(1))) // symbol
参考资料: