判断数据类型typeof、instanceof、Object.prototype.toString.call()、constructor
- 先来看看
instanceof
instanceof 期望左边是需要判断的 对象 ,注意是对象,所以instanceof是只能对于对象Object使用的,右边是标识对象的类(一个构造函数)
当instanceof判断左侧的对象Object是否是右侧类的一个实例的时候,也包含了对其父类的检测。如果instanceof的左侧不是一个对象,那么将返回false,如果右侧不是一个函数,那么将返回一个类型错误
instanceof的原理如下:
例子 o instanceof f
首先获取构造函数f的原型 f.prototype ,然后再原型链上查找,如果找的到,那么o就是f或者f父类的一个实例,返回true,若是不是的话,返回false。
另外的。由于右侧是构造函数,所以Object,Array,Data,Error,Function这些对象类型都是能放在右边的。instanceof的缺点在于不能获取类名,并且在客户端js中,因为每个窗口都有自己的执行上下文,包含了独有的一套全局变量和构造函数,这样会使得一个窗口的数组不是另一个窗口Array构造函数的实例。instanceof会返回false。
- 然后是
constructor
constructor是对象原型的一个属性,用来指向对象原型的构造函数。他会返回检测对象的类名。
注意:constructor的调用者不一定要是对象,因为若是在一个实例中找不到constructor属性,他会沿着原型链向上查找。
所以
var a = 1
a.constructor // [Function: Number]
a instanceof Number // false ,因为左边不是一个对象,是一个数值
所以constructor也是检测一个值是属于哪个类的一个方法。只不过他能返回类名,缺点也和instanceof一样,他在客户端js的多窗口情况下一样有问题。
typeof
typeof本质上是个一元运算符,他的操作数可以是任意类型。返回值是表示操作数类型的一个字符串
undefined "undefined"
null "object"
ture or false "boolean"
任意数字和NaN "number"
任意字符串 "string"
任意函数 "function"
出函数外的其他对象 "object"
值得一提的是,在ES6暂时性死区概念出现之前,typeof运算符几乎可以算一个百分百安全的操作。
Object.prototype.toString.call()
对象的类信息是一个字符串(class attribute)用以表示对象的类信息。现在只有一种简介的方法可以查询它,就是使用默认的toString()方法(继承自object。prototype)返回以下格式的字符串
[Object class]
但是由于很多对象中的toString()方法都改写了,为了使用正确的toString,我们使用Funcrtion.prototype中的call方法来确保这一点
Object.prototype.toString.call(a).slice(8,-1)
以上截取了返回字符串的第八到最后一位,也就是class值,但是类信息不能区别自定义类,他只会返回Object
null // => Null
Number // => Number
undefined // => Undefined
String // => String
Boolean // => Boolean
Object // => Object
Array // => Array
Date // => Date
Error // => Error
自定义对象 // Object