原文地址
掘金
求 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 btypeof 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) // truelet reg = /^/console.log(reg instanceof RegExp) // true
- (毛病) 只有以后类呈现在实例的原型链上检测的后果就是
true
,那么Object
类型检测的后果永远都是true
,如果实例的原型被批改了,即便检测的后果是true
,也是不精确的。 (毛病)
instanceof
不能检测根本数据类型。// 呈现在原型链上的类型都被判断成truelet ary = []console.log(ary instanceof Object) // truefunction fn(){}fn.prototype = Array.prototype // 原型被批改了let f = new fn()console.log(f instanceof Array) // trueconsole.log(f instanceof Function) // false// 不能检测根本数组类型console.log(1 instanceof Number) //falseconsole.log('' instanceof String) //falseconsole.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.constructorary.constructor === String // falseary.constructor === Object // falselet a = 1a.constructor === Number // truelet s = ''s.constructor === String // true
(毛病)
constructor
和instanceof
有一样的缺点,就是constructor
能够被批改也就是重定向Number.prototype.constructor = 'abc'let a = 1a.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"