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

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的代码呢?

你可能感兴趣的:(做一个获取类型、判断类型的小工具)