如何编写一个功能完备的类型判断函数(判断数据类型全解)

137 阅读2分钟

本文主要介绍各种判断数据类型的方法,最终会写一个功能齐全的类型判断函数

typeof,toString(原型链), instanseof, isNaN, Array.isArray

js里的数据类型

基础数据类型:number, string, boolean,undefined, null, symbol

引用数据类型: Object,Class,Set,Map,Function,Promise,Generator,Proxy,Array

关于引用类型不太熟悉的小伙伴请戳这里,ES6入门

typeof可以用来判断基础数据类型,无法判断引用类型

let numberTag = 1  // 'number'
let stringTag = '' // 'string'
let undefinedTag = undefined // 'undefined'
let nullTag = null // 'object'
let boolTag = true // 'boolean'
let symbolTag = Symbol() // 'symbol'
let numberObj = new Number(1) // 'object'
let stringObj = new String('obj') // 'object'
let boolObj = new Boolean(true) // 'object'
let arr = [] // 'object'

可以看到基础数据类型是可以判断的,引用类型是无法判断的

现在可以看到我们的type判断函数实现了判断基础数据类型的能力

function type(value) {
    if(typeof value === 'object') { // 引用类型
        if(!value) { // null
            return 'null'
        }
    } else { // 不是对象使用typeof 判断
        return typeof value
    }
}

toString方法

toString方法是调用实例的原型链方法进行判断的

风险:恶意覆盖原型链

let arr = [] // 返回数组元素字符串
let obj = {}// [object Object]
let classO = class {}// 返回类
new classO()// [object Object]
let classS = class {
    toString() {
        return '我覆盖了class的toString方法'
    }
}
// 返回类

new classS()
// '我覆盖了class的toString方法'
function functionO () {}
// 返回函数
let set = new Set()// [object Set]
let map = new Map()// [object Set]
var proxy = new Proxy({}, {
    get: function (target, propKey, receiver) {
      return Reflect.get(target, propKey, receiver);
    },
    set: function (target, propKey, value, receiver) {
      return Reflect.set(target, propKey, value, receiver);
    }
  });
  // [object Object]
  let promise = new Promise(() => {})
  // [object Promise]
  function* generator() {
    yield 'hello';
    yield 'world';
    return 'ending';
  }
// 返回函数

Set 为 [object Set]

Map为 [object Map]

Promise为 [object Promise]

Class,Proxy实例为[object Object]

toString方法无法判断函数,迭代器函数,数组

instansof运算符

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

风险:原型链覆盖

instansoff运算符可以判断所有的引用类型的原型

function type(value) {
    if(Array.isArray(value)) {
        return 'array'
    }
    if(isNaN(value)) {
        return 'NaN'
    }
    if(typeof value === 'object') {
        if(!value) {
            return 'null'
        } else {
            if(value instanceof Function) {
                return 'function'
            } else if(value instanceof Set) {
                return 'set'
            } else if(value instanceof Map) {
                return 'map'
            } else if(value instanceof Promise) {
                return 'promise'
            } else if(value instanceof Object)   {
                return 'object'
            }
        }
    } else {
        return typeof value
    }
}