原文地址
掘金
求 star
思維導(dǎo)圖
JS 中的類型
- 基本類型歧匈,
number健爬,string留夜,null包警,undefined撬碟,Boolean
诞挨,es6 新增的symbol
莉撇,es11
中的bigint
總共 7 種基本類型 - 引用類型:
object,function
亭姥。
數(shù)據(jù)類型的檢測(cè)方式
數(shù)據(jù)類型的檢測(cè)的方法中共有四種
typeof, instanceof, Object.prototype.toString.call(), constructor
一稼钩、typeof
typeof 檢測(cè)原理是:在計(jì)算機(jī)底層
根據(jù)js數(shù)據(jù)類型的二進(jìn)制的值進(jìn)行檢測(cè)的
。
-
typeof
檢測(cè)類型后的返回值是一個(gè)字符串
达罗,ES5 中對(duì)于一個(gè)為定義的變量判斷類型也會(huì)拋出字符串undefined
坝撑,而不是報(bào)錯(cuò)。但是用let, const
聲明的變量也能會(huì)導(dǎo)致暫時(shí)性死區(qū)粮揉,拋出ReferenceError
巡李。
typeof undefined //"undefined"
typeof a // "undefined"
typeof b // "ReferenceError"
let b
typeof 12 //"number"
typeof NaN //"number"
typeof '' //"string"
typeof 1n //"bigint"
typeof function(){} //"function"
- (缺點(diǎn))
typeof
可以檢測(cè)除了null
類型以外的數(shù)據(jù)型。null
被檢測(cè)成object
這是一個(gè)歷史遺留的 bug扶认。 - (缺點(diǎn))
typeof
不能檢測(cè)出具體的object
類型侨拦,因?yàn)閷?duì)象類型的二進(jìn)制開頭都是 000。比如typeof [] //"object"
檢測(cè)數(shù)組辐宾,正則狱从,日期等。 - 其他類型的二進(jìn)制叠纹,
000
對(duì)象季研,00000...
null,1
整數(shù)誉察,010
浮點(diǎn)數(shù) 与涡,100
字符串,110
布爾值 持偏,-2^30
undefined
typeof {} // "object"
typeof [] // "object"
typeof /^/ // "object"
typeOf 判斷函數(shù)為什么可以判斷出是 function 類型而不是 object
JS 中雖然函數(shù)也是對(duì)象驼卖,但是
typeOf
判斷函數(shù)是會(huì)調(diào)用call
方法來判斷。所以能判斷出function
思考:typeof null 檢測(cè)出來的結(jié)果為什么是 object
typeof
是根據(jù)二進(jìn)制值來判斷數(shù)據(jù)類型的鸿秆,null
的二進(jìn)制值是 000酌畜,而object
類型的二進(jìn)制值都是 000 開頭的,所以typeof
檢測(cè)null
是也被檢測(cè)成object
卿叽,這是一個(gè)歷史里留下來的bug
思考:0.1 + 0.2 !== 0.3 成立原因
二桥胞、濫竽充數(shù)的 instanceof
instanceof
檢測(cè)機(jī)制是:判斷右側(cè)的類型是否出現(xiàn)在左側(cè)實(shí)例的原型鏈上,出現(xiàn)了返回的結(jié)果就是true 否則是 false
附帽。
-
instanceof
判斷返回的結(jié)果是一個(gè) Boolean 值埠戳。 -
instanceof
是用來檢測(cè)當(dāng)前的實(shí)例是否屬于某個(gè)類的〗栋纾可以用來解決typeof
無法檢測(cè)具體的對(duì)象類型的問題整胃。
let ary = []
console.log(ary instanceof Array) // true
let reg = /^/
console.log(reg instanceof RegExp) // true
- (缺點(diǎn)) 只要當(dāng)前類出現(xiàn)在實(shí)例的原型鏈上檢測(cè)的結(jié)果就是
true
,那么Object
類型檢測(cè)的結(jié)果永遠(yuǎn)都是true
喳钟,如果實(shí)例的原型被修改了屁使,即使檢測(cè)的結(jié)果是true
在岂,也是不準(zhǔn)確的。 - (缺點(diǎn))
instanceof
不能檢測(cè)基本數(shù)據(jù)類型蛮寂。
// 出現(xiàn)在原型鏈上的類型都被判斷成true
let ary = []
console.log(ary instanceof Object) // true
function fn(){}
fn.prototype = Array.prototype // 原型被修改了
let f = new fn()
console.log(f instanceof Array) // true
console.log(f instanceof Function) // false
// 不能檢測(cè)基本數(shù)組類型
console.log(1 instanceof Number) //false
console.log('' instanceof String) //false
console.log(false instanceof Boolean) //false
思考蔽午,模擬實(shí)現(xiàn) instanceof
思路:根據(jù)左側(cè)實(shí)例的原型鏈上是否出現(xiàn)右側(cè)的類型進(jìn)行判斷結(jié)果。即
實(shí)例.__proto__ === 類.prototype
酬蹋,則是true 否則是 false及老。對(duì)原型和原型鏈不熟悉的可以看 面試 | 你不得不懂得 JS 原型和原型鏈。
function _instanceof(example, classP) {
let proto = Object.getPrototypeOf(example),
classPrototype = classP.prototype
while (true) {
if (proto === classPrototype) {
return true
}
if (proto === null) {
return false
}
proto = Object.getPrototypeOf(proto)
}
_instanceof([], Array) //true
_instanceof('', Array) // false
_instanceof('', Object) // true
三范抓、濫竽充數(shù)的 constructor
instanceof
檢測(cè)機(jī)制是:constructor
存放的就是構(gòu)造函數(shù)本身骄恶,通過存放的構(gòu)造函數(shù)來檢測(cè)類型。不熟悉constructor
的也可以看 面試 | 你不得不懂得 JS 原型和原型鏈匕垫。
-
constructor
可以檢測(cè)基本類型僧鲁,這點(diǎn)比instanceof
好用
let ary = []
ary.constructor === Array // true,ary.constructor ==> Array.prototype.constructor
ary.constructor === String // false
ary.constructor === Object // false
let a = 1
a.constructor === Number // true
let s = ''
s.constructor === String // true
- (缺點(diǎn))
constructor
和instanceof
有一樣的缺陷象泵,就是constructor
可以被修改也就是重定向
Number.prototype.constructor = 'abc'
let a = 1
a.constructor === Number // false
四寞秃、Object.prototype.toString.call(),標(biāo)準(zhǔn)檢測(cè)類型
檢測(cè)機(jī)制是:利用
Object.prototype.toString
返回實(shí)例所屬類的信息偶惠,通過改變toString
中的this
指向來返回指定參數(shù)的類型厚柳。
-
Object.prototype.toString
返回的格式固定是'[object xxx]'
逗概,可以檢測(cè)任意類型
Object.prototype.toString.call(1) //"[object Number]"
Object.prototype.toString.call('') //"[object String]"
Object.prototype.toString.call(null) //"[object Null]"
Object.prototype.toString.call(undefined) //"[object Undefined]"
Object.prototype.toString.call(Symbol()) //"[object Symbol]"
Object.prototype.toString.call([]) //"[object Array]"
Object.prototype.toString.call(function(){}) //"[object Function]"
Object.prototype.toString.call({}) //"[object Object]"
- (缺點(diǎn)) 不能直接提取出數(shù)據(jù)類型绪穆,還需要轉(zhuǎn)變才拿到直接的類型
五芥牌、其他快捷判斷方式
isNumber()
,isNaN()
,Array.isArray()
呼盆。吧彪。土铺。
六萤悴、封裝一個(gè)萬能的檢測(cè)方法 toType()
1. jQuery 中的類型檢測(cè)
(function () {
// jquery 中的 toType
let class2type = {},
toString = class2type.toString
// 設(shè)定類型映射表
let arrType = ['Number', 'String', 'Boolean', 'Symbol', 'Array', 'Date', 'Error', 'RegExp', 'Function', 'Object']
arrType.forEach(item => {
class2type[`[object ${item}]`] = item.toLowerCase()
});
function toType(checkType) {
if (checkType === null || checkType == undefined) {
return checkType + ''
}
return typeof checkType == 'object' || typeof checkType == 'function' ? class2type[toString.call(checkType)] : typeof checkType
}
window.toType = toType
})()
toType(1) //"number"
toType('') //"string"
toType(null) //"null"
toType(undefined) //"undefined"
toType({}) //"object"
toType(function(){}) //"function"
toType([]) //"array"
本質(zhì)上還是利用了
Object.prototype.toString.call()
2. 自封裝一個(gè)更簡(jiǎn)單的 selfType()
(function () {
function selfType(checkType) {
let res = {}.toString.call(checkType).split(' ')[1].split(']')[0].toLowerCase() // 可以使用正則
return res
}
window.selfType = selfType
})()
selfType('') //"string"
selfType(1) //"number"
selfType(null) //"null"
selfType(undefined) //"undefined"
selfType(function(){}) //"function"
selfType({}) //"object"