JavaScript 数据类型与类型判断
前言
JS 中的数据经常打交道,与之相关的数据类型,在平常开发中却不是很在意,只有在开发中遇到问题才会去搜索相关知识,而本身没有相关的知识储备。
上周面试中,面试官问了几个问题,慢慢意识到自己基础并不扎实。
Q1: JS 有哪些数据类型?
A: number
,boolean
,string
,null
,undefined
,symbol
, object
Q2: 有哪些方法判断数据类型?
A: typeof
, instanceof
Q3: 还有别的方法? A: ??? 还有嘛(疑问: Array.isArray 对,这个方法可以判断数组,那还有别的方法可以判断别的数据类型嘛?)
Q4: 哪些是原始类型?
A: number
,boolean
,string
,undefined
,symbol
。object
不是原始类型。(疑问:那 null
呢? typeof null
也是 object
, 函数呢,Date呢,正则呢, 那怎么判断某个类型是不是原始类型?)
同时,最后面试官举了个数据类型的使用场景,在写组件的时候,写公共函数的时候,需要去校验参数的类型,如果参数不对,需要抛出对应的错误。
的确,健壮性足够强的代码,应该要考虑到很多的情况,而这些的基础都要明确数据类型。
1. 数据类型
解决 Q1, 即以下八种数据类型,其中对象类型又包含函数对象,日期对象等
MDN 中已经说明了,JS 中有 8 种数据类型(七种原始类型和对象类型):
解决 Q4, 即以下七种类型是原始类型,其他对象类型都不是原始类型
七种原始类型: 1. number 2. string 3. boolean 4. null 5. undefined 6. bigint 7. symbol
原始类型存储的都是值,是没有属性或者方法的。 如 1.toString()
会报错,因为 1 这个基础类型没有 toString
方法。
注意: '1'.toString()
是可以的, 是因为在调用 toString
方法的时候,字符串 '1' 已经转为 字符串对象 了,而对象是有方法的。
对象类型: 除了原始类型,都是对象类型
标准对象,键值对 {}
函数对象
日期,Date 对象
数组,Array 对象
正则, RegExp 对象
错误,Error 对象
2. 数据类型
typeof 表达式
结果
typeof 1
number
typeof '1'
string
typeof true
boolean
typeof undefined
undefined
typeof function() {}
function
typeof Symbol('a')
symbol
typeof null
object
typeof {}
object
typeof new Date()
object
typeof /1/
object
typeof []
object
typeof new Error()
object
也就是说,typeof 可以检验出, number
,string
,boolean
,undefined
,function
, symbol
类型,而对于 null
和 其他的对象类型数据,返回值都是 object
,不能区分。
那如何区分, null, 标准对象,函数对象,日期对象,数组对象,错误对象和正则对象呢?
解决 Q2,Q3, 即还可以使用 Object.prototype.toString() 方法来判断类型
答案是 Object.prototype.toString()
Object.prototype.toString.call()
结果
Object.prototype.toString.call(1)
[object Number]
Object.prototype.toString.call('1')
[object String]
Object.prototype.toString.call(true)
[object Boolean]
Object.prototype.toString.call(undefined)
[object Undefined]
Object.prototype.toString.call(function() {})
[object Function]
Object.prototype.toString.call(Symbol(1))
[object Symbol]
Object.prototype.toString.call(null)
[object Null]
Object.prototype.toString.call({})
[object Object]
Object.prototype.toString.call(new Date())
[object Date]
Object.prototype.toString.call(/1/)
[object RegExp]
Object.prototype.toString.call([])
[object Array]
Object.prototype.toString.call(new Error())
[object Error]
接下来写一个 type
函数,该函数返回任意数据的数据类型。
至此,我们能判断原始类型以及一些对象类型。
3. 额外的 Utils 方法
3.1 isWindow
依据: window 对象有 window 属性指向自身。
3.2 isEmptyObject
依据: 空对象上没有属性
3.3 isElement
依据: DOM 元素的 nodeType 为 1
3.4 isValidDate (是否为有效的日期对象)
依据: isNaN(new Date('foo')) === true
此外,我们可以再关注一下 Date 的一下奇怪行为:
4. 数据类型与内存
在 JS 中,每一个数据都需要一个内存空间,而内存空间又被分为: 栈内存(stack)与堆内存(heap)。
number
, boolean
, string
, null
, undefined
, symbol
这几种基础类型和函数,它们的值会存放在栈内存中。
而引用类型数据,如 Array
(所需内存大小不一样), 标准对象 {}
, 它们的值存放在堆内存中。
参考资料
Last updated