原文地址

掘金

求 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
  • (毛病) constructorinstanceof 有一样的缺点,就是 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"