1、使用typeof进行判断
一般使用typeOf判断基础数据类型,如下例子
let str = "123"
let num = 123
let bool = false
let undefin = undefined
let nul = null
let sym = Symbol('123')
let arr = [1, 23]
let obj = {
a: 1
}
function fn() {}
console.log(typeof (str)) // "string"
console.log(typeof (num)) // "number"
console.log(typeof (bool)) // "boolean"
console.log(typeof (undefin)) // "undefined
console.log(typeof (nul)) // "object"
console.log(typeof (sym)) // "symbol"
console.log(typeof (arr)) // "object"
console.log(typeof (obj)) // "object"
console.log(typeof (fn)) // "function"
从上面的例子可以看出,使用typeof判断null的时候返回的object,这个是js设计时留下的bug,我们记住它就行了。 使用typeOf不能区分对象和数据,他们俩使用typeOf都返回object,接下来我们介绍另外一种数据类型判断条件,它主要是判断是对象是否是new出来的实例。
2、使用instanceOf 进行类型判断
想必 instanceof 的方法你也听说过,我们 new 一个对象,那么这个新对象就是它原型链继承上面的对象了,通过 instanceof 我们能判断这个对象是否是之前那个构造函数生成的对象,这样就基本可以判断出这个新对象的数据类型。下面通过代码来了解一下
let Car = function() {}
let benz = new Car()
benz instanceof Car // true
let car = new String('Mercedes Benz')
car instanceof String // true
let str = 'Covid-19'
str instanceof String // false
下面是自己实现的instanceof
function myInstanceof(left, right) {
// 这里先用typeof来判断基础数据类型,如果是,直接返回false
if(typeof left !== 'object' || left === null) return false;
// getProtypeOf是Object对象自带的API,能够拿到参数的原型对象
let proto = Object.getPrototypeOf(left);
while(true) { //循环往下寻找,直到找到相同的原型对象
if(proto === null) return false;
if(proto === right.prototype) return true;//找到相同原型对象,返回true
proto = Object.getPrototypeof(proto);
}
}
// 验证一下自己实现的myInstanceof是否OK
console.log(myInstanceof(new Number(123), Number)); // true
console.log(myInstanceof(123, Number));
以上这两种方法都是有自己的缺陷的:typeof只能判断基础数据类型,并且null由于历史原因也不能准确判断,复杂数据类型除了function其他的不能准确判断;instanceof能判断复杂的数据类型,但是不能判断基础数据类型。
3、使用Object.prototype.toString判断(终极判断)
toString是Object上的原型方法,调用此方法,统一返回 “[object Xxx]” (注意第二个单词首个字母是大写),object队可以直接调用此方法,返回 “[object Object]”,如果其他数据类型调用此方法得使用call调用才能正确返回,至于为啥要抵用call,可自行查call的使用方法。
Object.prototype.toString({}) // "[object Object]"
Object.prototype.toString.call({}) // 同上结果,加上call也ok
Object.prototype.toString.call(1) // "[object Number]"
Object.prototype.toString.call('1') // "[object String]"
Object.prototype.toString.call(true) // "[object Boolean]"
Object.prototype.toString.call(function(){}) // "[object Function]"
Object.prototype.toString.call(null) //"[object Null]"
Object.prototype.toString.call(undefined) //"[object Undefined]"
Object.prototype.toString.call(/123/g) //"[object RegExp]"
Object.prototype.toString.call(new Date()) //"[object Date]"
Object.prototype.toString.call([]) //"[object Array]"
Object.prototype.toString.call(document) //"[object HTMLDocument]"
Object.prototype.toString.call(window) //"[object Window]"
整合以上3中方法,得出下面的的终极判断类型函数
function getType(obj){
let type = typeof obj;
if (type !== "object") { // 先进行typeof判断,如果是基础数据类型,直接返回
return type;
}
// 对于typeof返回结果是object的,再进行如下的判断,正则返回结果
return Object.prototype.toString.call(obj).replace(/^\[object (\S+)\]$/, '$1'); // 注意正则中间有个空格
}
/* 代码验证,需要注意大小写,哪些是typeof判断,哪些是toString判断?思考下 */
getType([]) // "Array" typeof []是object,因此toString返回
getType('123') // "string" typeof 直接返回
getType(window) // "Window" toString返回
getType(null) // "Null"首字母大写,typeof null是object,需toString来判断
getType(undefined) // "undefined" typeof 直接返回
getType() // "undefined" typeof 直接返回
getType(function(){}) // "function" typeof能判断,因此首字母小写
getType(/123/g) //"RegExp" toString返回