共计 4387 个字符,预计需要花费 11 分钟才能阅读完成。
原文地址
掘金
求 star
思维导图
JS 中的类型
- 根本类型,
number,string,null,undefined,Boolean
,es6 新增的symbol
,es11
中的bigint
总共 7 种根本类型 -
援用类型:
object,function
。数据类型的检测形式
数据类型的检测的办法中共有四种
typeof, instanceof, Object.prototype.toString.call(), constructor
一、typeof
typeof 检测原理是:在计算机底层
依据 js 数据类型的二进制的值进行检测的
。
-
typeof
检测类型后的返回值是一个字符串
,ES5 中对于一个为定义的变量判断类型也会抛出字符串undefined
,而不是报错。然而用let, const
申明的变量也能会导致暂时性死区,抛出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"
- (毛病)
typeof
能够检测除了null
类型以外的数据型。null
被检测成object
这是一个历史遗留的 bug。 - (毛病)
typeof
不能检测出具体的object
类型,因为对象类型的二进制结尾都是 000。比方typeof [] //"object"
检测数组,正则,日期等。 - 其余类型的二进制,
000
对象,00000...
null,1
整数,010
浮点数,100
字符串,110
布尔值,-2^30
undefined
typeof {} // "object"
typeof [] // "object"
typeof /^/ // "object"
typeOf 判断函数为什么能够判断出是 function 类型而不是 object
JS 中尽管函数也是对象,然而
typeOf
判断函数是会调用call
办法来判断。所以能判断出function
思考:typeof null 检测进去的后果为什么是 object
typeof
是依据二进制值来判断数据类型的,null
的二进制值是 000,而object
类型的二进制值都是 000 结尾的,所以typeof
检测null
是也被检测成object
,这是一个历史里留下来的 bug
思考:0.1 + 0.2 !== 0.3 成立起因
二、冒名顶替的 instanceof
instanceof
检测机制是:判断右侧的类型是否呈现在左侧实例的原型链上,呈现了返回的后果就是 true 否则是 false
。
instanceof
判断返回的后果是一个 Boolean 值。-
instanceof
是用来检测以后的实例是否属于某个类的。能够用来解决typeof
无奈检测具体的对象类型的问题。let ary = [] console.log(ary instanceof Array) // true let reg = /^/ console.log(reg instanceof RegExp) // true
- (毛病) 只有以后类呈现在实例的原型链上检测的后果就是
true
,那么Object
类型检测的后果永远都是true
,如果实例的原型被批改了,即便检测的后果是true
,也是不精确的。 -
(毛病)
instanceof
不能检测根本数据类型。// 呈现在原型链上的类型都被判断成 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 // 不能检测根本数组类型 console.log(1 instanceof Number) //false console.log('' instanceof String) //false console.log(false instanceof Boolean) //false
思考,模仿实现 instanceof
思路:依据左侧实例的原型链上是否呈现右侧的类型进行判断后果。即
实例.__proto__ === 类.prototype
,则是 true 否则是 false。对原型和原型链不相熟的能够看 面试 | 你不得不懂得 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
三、冒名顶替的 constructor
instanceof
检测机制是:constructor
寄存的就是构造函数自身,通过寄存的构造函数来检测类型。不相熟constructor
的也能够看 面试 | 你不得不懂得 JS 原型和原型链。
-
constructor
能够检测根本类型,这点比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
-
(毛病)
constructor
和instanceof
有一样的缺点,就是constructor
能够被批改也就是重定向Number.prototype.constructor = 'abc' let a = 1 a.constructor === Number // false
四、Object.prototype.toString.call(),规范检测类型
检测机制是:利用
Object.prototype.toString
返回实例所属类的信息,通过扭转toString
中的this
指向来返回指定参数的类型。
-
Object.prototype.toString
返回的格局固定是'[object xxx]'
,能够检测任意类型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]"
- (毛病) 不能间接提取出数据类型,还须要转变才拿到间接的类型
五、其余快捷判断形式
isNumber()
,isNaN()
,Array.isArray()
。。。
六、封装一个万能的检测办法 toType()
1. jQuery 中的类型检测
(function () {
// jquery 中的 toType
let class2type = {},
toString = class2type.toString
// 设定类型映射表
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"
实质上还是利用了
Object.prototype.toString.call()
2. 自封装一个更简略的 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"