这个问题之前也没有想过,前不久有人问到这个问题,则回去了解了一下。首先给一个实例图:

表达式


ypeof true

‘boolean’

typeof 56

number

typeof “567”

string

typeof function(){}

‘function’

typeof [1,2,3]

‘object’

typeof {name:‘张三’,age:22}

‘object’

typeof null

‘object’

typeof undefined

‘undefined’

typeof unknownVariable

‘undefined’

由上诉表格可见,对于布尔值 数字 字符串以及函数这几种简单类型typeof是可以正确判断的,但是对于其他类型则可能会出现不可预期的错误。
解决办法:
判断Array :Array.isArray(arr) 准确判断一个数据类型是否为Array返回值为Boolean。
//infoVar 是需要判断类型的数据。
判断null:infoVar === null
判断某个全局变量是否存在: typeof window.infoVar ===‘undefined’。

函数内部判断某个变量是否存在用typeof infoVar=== ‘undefined’。
但通过以上解决方法,没有办法判断 typeof infoVar=== ‘undefined’的时候具体是定义还是未定义
于是可以封装成一个函数:

function isDefined(va) {
    //var va;
    //var va = null;
    //var va = 'xxxx';
    try{
        // 已经声明
        // 判断是否已经定义
        if (va === undefined){ 
        // 不能使用 ==,因为当 "var va = null;"时 被判定为未定义是错误的。
        //if (typeof  va === 'undefined'){  // 这种方式也是不可取的。
            // 未定义
            console.log("变量未定义.");
        }else {
            // 已经定义了,可能为null 
            console.log("变量已定义.");
        }
    } catch(e){
        // va 未声明
       console.log("变量未声明,");
    }
}

对于判断具体数组或是对象的判断则还有以下方法:

1.instanceof
数组也是对象的一种,使用instanceof都会返回true

console.log(arr instanceof Array);      //true
console.log(arr instanceof Object);     //true
console.log(obj instanceof Array);      //false
console.log(obj instanceof Object);     //true

判断原理: instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性,意思就是该变量通过原型链上能否找到构造函数的prototype 属性。

Array.prototype === arr.__proto__
 Object.prototype === arr.__proto__.__proto__

2.constructor

console.log(arr.constructor === Array);      //true
console.log(arr.constructor === Object);     //false
console.log(obj.constructor === Object);     //true

3.Object.prototype.toString.call()

Object.prototype.toString.call()方法可以精准判断变量类型,它返回[object constructorName]的字符串格式,constructorName是call参数的函数名

console.log(Object.prototype.toString.call([1,2,3]));   //[object Array]
        console.log(Object.prototype.toString.call({name:'张三',age:22}));   //[object Object]
        console.log(Object.prototype.toString.call(123));   //[object Number]
        console.log(Object.prototype.toString.call(NaN));   //[object Number]
        console.log(Object.prototype.toString.call("123"));   //[object String]
        console.log(Object.prototype.toString.call(null));   //[object Null]
        console.log(Object.prototype.toString.call(false));   //[object Boolean]
        console.log( Object.prototype.toString.call(undefined));   //[object Undefined]
        console.log( Object.prototype.toString.call(Symbol()));   //[object Symbol]

由于Object.prototype.toString.call()返回的不只是数据类型名称 所以可以简单的函数处理:
封装简单工具函数判断类型:

**
 * 判断一个变量哪种类型
 * @param {*} obj - 待判断变量
 * @returns {string} 类型名称
 */
export function typeOf(obj) {
  return toString.call(obj).slice(8, -1).toLowerCase()
}

总结

对于简单数据类型可以用typeof 判断 而对于数组对象以及其余复杂相对类型则需要用到其他方法 而Object.prototype.toString.call() 是更加精准的,所以建议使用。

声明

本篇内容根据两位博主博客@Yucihent,@BenjaminShih整合而得,仅作为一个学习笔记保留。