美文网首页ES6的基础知识前端开发那些事儿
做一个获取类型、判断类型的小工具

做一个获取类型、判断类型的小工具

作者: 自然框架 | 来源:发表于2021-10-24 20:53 被阅读0次

    JavaScript 的类型真的是一言难尽,最简单的判断类型的方法是使用 typeof,相信大家都会用,但是得到的类型却比较“宽泛”。

    比如 typeof foo ,如果得到的是 'object',那么 foo 可能是object,也可能是 array,还可能是date,也可能是 map,如果要细分的话,还需要再次进行判断。

    另外判断类型的方式也不统一,比如上面说的array,用typeof得到的是 object,那么想看看到底是不是数组怎么办呢?到网上搜索会发现各种方法,最后找到了 Array.isArray(foo) 的方法。

    这个挺简单的,但是map呢?并没有Map.isMap 的验证方式。

    咱们能不能统一一下验证风格呢?

    翻了一下vue的源码(shared):

    const hasOwnProperty = Object.prototype.hasOwnProperty;
    const hasOwn = (val, key) => hasOwnProperty.call(val, key);
    const isArray = Array.isArray;
    const isMap = (val) => toTypeString(val) === '[object Map]';
    const isSet = (val) => toTypeString(val) === '[object Set]';
    const isDate = (val) => val instanceof Date;
    const isFunction = (val) => typeof val === 'function';
    const isString = (val) => typeof val === 'string';
    const isSymbol = (val) => typeof val === 'symbol';
    const isObject = (val) => val !== null && typeof val === 'object';
    const isPromise = (val) => {
        return isObject(val) && isFunction(val.then) && isFunction(val.catch);
    };
    

    这个是不是有点太奔放了?

    获取类型

    俗话说的好,自己动手丰衣足食。我们先来做一个获取类型的函数,最全面的方式就是 Object.prototype.toString.call(obj),那么我们来用这个获取类型。

    只是他返回的是这种形式:'[object Array]'。有点麻烦,我们做个“字典”来翻译一下。

      /**
       * 做一个字典,映射类型
       */
      const dicTypeName = {
        '[object Object]': 'object',
        '[object Array]': 'array',
        '[object Map]': 'map',
        '[object Set]': 'set',
        '[object Function]': 'function',
        '[object AsyncFunction]': 'async',
        '[object Promise]': 'promise',
        '[object Symbol]': 'symbol',
        '[object String]': 'string',
        '[object Number]': 'number',
        '[object BigInt]': 'bigInt',
        '[object RegExp]': 'regExp',
        '[object Date]': 'date',
        '[object Math]': 'math',
        '[object Null]': 'null',
        '[object Undefined]': 'undefined'
      }
    

    穷举了一下我能想到和找到的类型,如果有遗漏还请大家多多帮忙,先谢过了。

    没想到吧,至少十六种。当然 Math 似乎不用判断,因为没有实例。
    Promise、async function 也都能区分开,应该是比较全面的了。
    只是Proxy的还是区分不出来,返回的是 object。

    我们写一些函数来实现功能

      /**
       * 用 call 的方式获取类型
       * @param {*} val 要验证的实例
       * @returns
       * *   '[object Object]',
       * *   '[object Array]',
       * *   '[object Map]',
       * *   '[object Set]',
       * *   '[object Function]',
       * *   '[object AsyncFunction]',
       * *   '[object Promise]',
       * *   '[object Symbol]',
       * *   '[object String]',
       * *   '[object Number]',
       * *   '[object BigInt]',
       * *   '[object RegExp]',
       * *   '[object Date]',
       * *   '[object Math]',
       * *   '[object Null]',
       * *   '[object Undefined]'
       */
      const toTypeString = (val) => {
        return Object.prototype.toString.call(val)
      }
      
      /**
       * 获取具体类型
       * @param {*} val 要验证的实例
       * @returns 
       * *   'function',
       * *   'async',
       * *   'object',
       * *   'array',
       * *   'string',
       * *   'number',
       * *   'bigInt',
       * *   'regExp',
       * *   'date',
       * *   'map',
       * *   'set',
       * *   'promise',
       * *   'symbol',
       * *   'math',
       * *   'null',
       * *   'undefined'
       */
       const typeName = (val) => {
        const re = dicTypeName[toTypeString(val)]
        if (typeof re === 'string')
          return re
        else
          return 'unknown'
      }
    
    

    验证类型

    有时候我们只想知道是不是数组,不需要知道是不是其他的某个类型,这时候可以做一个统一风格的验证方式。

    
      const hasOwnProperty = Object.prototype.hasOwnProperty
      const hasOwn = (val, key) => hasOwnProperty.call(val, key)
    
      const isFunction = (val) => typeof val === 'function'
      const isAsync = (val) => toTypeString(val) === '[object asyncFunction]'
      const isObject = (val) => val !== null && typeof val === 'object'
      const isArray = Array.isArray
      const isString = (val) => typeof val === 'string'
      const isNumber = (val) => toTypeString(val) === '[object Number]'
      const isBigInt = (val) => toTypeString(val) === '[object BigInt]'
      const isRegExp = (val) => toTypeString(val) === '[object RegExp]'
      const isDate = (val) => val instanceof Date
    
      const isMap = (val) => toTypeString(val) === '[object Map]'
      const isSet = (val) => toTypeString(val) === '[object Set]'
      const isPromise = (val) => toTypeString(val) === '[object Promise]'
      const isSymbol = (val) => typeof val === 'symbol'
    
      const isNullOrUndefined = (val) => {
        if (val === null) return true
        if (typeof val === 'undefined') return true
        return false
      }
    
    export {
      toTypeString, // Object.prototype.toString.call(val)
      typeName,
    
      hasOwnProperty,
      hasOwn,
    
      isFunction,
      isAsync,
      isObject,
      isArray,
      isString,
      isNumber,
      isBigInt,
      isRegExp,
      isDate,
      isMap,
      isSet,
      isPromise,
      isSymbol, 
     
      isNullOrUndefined
    }
    

    好吧,还是参考了vue的写法。话说,为啥不直接用vue的代码呢?

    相关文章

      网友评论

        本文标题:做一个获取类型、判断类型的小工具

        本文链接:https://www.haomeiwen.com/subject/gjtdaltx.html