第一种:typeof
typeof返回被判断数据的类型的字符串
一些特殊例子如下
typeof null //'object'
typeof [1,2,3] //'object'
typeof new Date() //'object'
精确区分普通对象和数组,请使用 Array.isArray() 或者 Object.prototype.toString.call()
如果使用 new 操作符来创建数据,会出现什么结果呢
let str = new String('String')
let num = new Number(100)
typeof str //'object'
typeof num //'object'
这是因为,除了 Function 构造函数之外,其他的构造函数的类型都是 'object'
由此可见,typeof 不能判断 null 和数组,而且由于 let 和 const 的出现,使得 typeof 可能会报引用错误
第二种:instanceof
instanceof用于检测构造函数的 prototype 属性是否出现于在左边对象的原型链中
一个简陋的实现 instanceof
function _instanceof(left, right){
if(typeof left!== 'object' || left===null)return
if(typeof right !== 'function')return
let proto=Object.getPrototypeOf(left)
let prototype=right.prototype
while(true){
if(proto===null){return false}
if(proto===prototype){return true}
proto=Object.getPrototypeOf(proto)
}
}
注意,instanceof 不能判断 null 和 undefined,因为对它们使用 Object.getPrototypeOf 会直接报错,下面是一些特殊情况
let str='hello'
let string=new String('hi')
str instanceof String //false
str instanceof Object //false
string instanceof String //true
这是因为 str 只是一个 string 类型的值,但它并不是 String对象的实例,同样,它也不是一个 Object对象的实例。
但是你会发现 Object.getPrototypeOf(str)=== String.prototype
第三种 Object.prototype.toString()
数组,数字,函数都覆盖了 toString 方法,我们想要判断数据类型,必须使用 Object 原型对象上的 toString,这就是在使用时需要使用 call 来调用的原因
如果你直接调用,即使你传了参数,也会被忽略,此时 toString 内部的 this 是 Object.prototype,结果永远都是 '[object Object]'
Object.prototype.toString(1)
'[object Object]'