typeof 和 instanceof 判断的问题 #
使用 typeof
判断基本数据类型(包括 symbol)对 null 或引用类型判断不准确。
typeof Array //'object'
typeof Object //'object'
typeof Date //'object'
typeof null //'object'
得到的判断不准确
使用instanceof
来判断 null,则不把 null 当成 Object ,
null instanceof null //报错 右边要是object
null instanceof Object //false 则不把null当成Object
instanceof 只能判断引用类型 instanceof 也无法判断准确类型 例如数组 Object
console.log([] instanceof Object);//true
console.log([] instanceof Array);//true
对一个变量的类型来进行比较准确的判断使用 Object.prototype.toString.call()
Object.prototype.toString.call(null) // "[object Null]"
Object.prototype.toString.call()为什么要加 call(); #
Object.prototype.toString 可以返回当前调用者的对象类型。 Object.prototype.toString()会返回[object, [[class]]]的字符串
其中[[class]]会返回 es 定义的对象类型,包含"Arguments", “Array”, “Boolean”, “Date”, “Error”, “Function”, “JSON”, “Math”, “Number”, “Object”, “RegExp”, 和 “String”; 再加上 es5 新增加的返回[object Undefined]和[object Null]
Object.prototype.toString()中,他的调用者永远都是 Object.prototype;所以,在不加 call()情况下,我们的出来的结果永远都是 '[object Object]'
call(),是为了改变 Object.prototype.toString 这个函数都指向。让 Object.prototype.toString 这个方法指向我们所传入的数据。
每个数据类,他们都重写了 toString()方法。所以,如果我们拿数据本身去 toString(),是得不到对象类型的。 必须用 Object.prototype.toString
因为有原型链,找到顶层的原型对象,再去 call 改变 this 指向
Vue 源码做类型检测时,也很喜欢 typeof,instanceof 和 Array.isArray()。只是在做严格的类型检测时,会使用到 Object.prototype.toString。
相较于 typeof、instanceof、Array.isArray,Object.prototype.toString.call 更可靠,甚至 null,它都检测出来了
var _toString = Object.prototype.toString;
function toRawType (value) {
return _toString.call(value).slice(8, -1)
}
/**
* Strict object type check. Only returns true
* for plain JavaScript objects.
*/
function isPlainObject (obj) {
return _toString.call(obj) === '[object Object]'
}
总结 #
基本的类型检测用 typeof,引用类型检测用 instanceof,还有专门用于检查是不是数组的 Array.isArray()