function Person(){ } function Student(){ } Student.prototype = new Person(); var John = new Student(); console.log(John.constructor==Student); // false console.log(John.constructor==Person); // true
在上面的例子中,Student原型中的constructor被修改为指向到Person,导致检测不出实例对象John真实的构造函数。
同时,使用instaceof和construcor,被判断的array必须是在当前页面声明的!比如,一个页面(父页面)有一个框架,框架中引用了一个页面(子页面),在子页面中声明了一个array,并将其赋值给父页面的一个变量,这时判断该变量,Array == object.constructor;会返回false; 原因:
1、array属于引用型数据,在传递过程中,仅仅是引用地址的传递。
2、每个页面的Array原生对象所引用的地址是不一样的,在子页面声明的array,所对应的构造函数,是子页面的Array对象;父页面来进行判断,使用的Array并不等于子页面的Array;切记,不然很难跟踪问题!
4. 使用Object.prototype.toString.call
我们先不管这个是什么,先来看看他是怎么检测变量类型的:
console.log( Object.prototype.toString.call(num), Object.prototype.toString.call(str), Object.prototype.toString.call(bool), Object.prototype.toString.call(arr), Object.prototype.toString.call(json), Object.prototype.toString.call(func), Object.prototype.toString.call(und), Object.prototype.toString.call(nul), Object.prototype.toString.call(date), Object.prototype.toString.call(reg), Object.prototype.toString.call(error) ); // '[object Number]' '[object String]' '[object Boolean]' '[object Array]' '[object Object]' // '[object Function]' '[object Undefined]' '[object Null]' '[object Date]' '[object RegExp]' '[object Error]'
从输出的结果来看,Object.prototype.toString.call(变量)输出的是一个字符串,字符串里有一个数组,第一个参数是Object,第二个参数就是这个变量的类型,而且,所有变量的类型都检测出来了,我们只需要取出第二个参数即可。或者可以使用Object.prototype.toString.call(arr)=="object Array"来检测变量arr是不是数组。
我们现在再来看看ECMA里是是怎么定义Object.prototype.toString.call的:
复制代码 代码如下:
Object.prototype.toString( ) When the toString method is called, the following steps are taken:
1. Get the [[Class]] property of this object.
2. Compute a string value by concatenating the three strings “[object “, Result (1), and “]”.
3. Return Result (2)
上面的规范定义了Object.prototype.toString的行为:首先,取得对象的一个内部属性[[Class]],然后依据这个属性,返回一个类似于”[object Array]”的字符串作为结果(看过ECMA标准的应该都知道,[[]]用来表示语言内部用到的、外部不可直接访问的属性,称为“内部属性”)。利用这个方法,再配合call,我们可以取得任何对象的内部属性[[Class]],然后把类型检测转化为字符串比较,以达到我们的目的。
5. jquery中$.type的实现
在jquery中提供了一个$.type的接口,来让我们检测变量的类型:
console.log( $.type(num), $.type(str), $.type(bool), $.type(arr), $.type(json), $.type(func), $.type(und), $.type(nul), $.type(date), $.type(reg), $.type(error) ); // number string boolean array object function undefined null date regexp error
看到输出结果,有没有一种熟悉的感觉?对,他就是上面使用Object.prototype.toString.call(变量)输出的结果的第二个参数呀。
我们这里先来对比一下上面所有方法检测出的结果,横排是使用的检测方法, 竖排是各个变量:
类型判断
typeof
instanceof
constructor
toString.call
$.type
num
number
false
true
[object Number]
number
str
string
false
true
[object String]
string
bool
boolean
false
true
[object Boolean]
boolean
arr
object
true
true
[object Array]
array
json
object
true
true
[object Object]
object
func
function
true
true
[object Function]
function
und
undefined
false
-
[object Undefined]
undefined
nul
object
false
-
[object Null]
null
date
object
true
true
[object Date]
date
reg
object
true
true
[object RegExp]
regexp
error
object
true
true
[object Error]
error
优点
使用简单,能直接输出结果
能检测出复杂的类型
基本能检测出所有的类型
检测出所有的类型
-
缺点
检测出的类型太少
基本类型检测不出,且不能跨iframe
不能跨iframe,且constructor易被修改
IE6下undefined,null均为Object
-