var arr1=[1,2,3,4],arr2={a:1,b:2}
方法一:判断原型对象
arr1.__proto__==Array.prototype?
但是有一个问题。__proto__是一个隐藏属性 不是所有浏览器都支持使用 可用Object.getPrototypeOf(arr1)来代替。因此变成了:
Object.getPrototypeOf(arr1)==Array.prototype?
方法二:判断构造函数
arr1 instanceof Array ?
意思是arr1是否是Array的实例,即arr1是否是构造函数Array构造出来的。结果是一个布尔值
但是以上两种方法依然有缺陷。
如果设置arr2.__proto__==arr1;
即arr1可以使用的API arr2对象都可以使用。 因为arr2此时和arr1处于同一条原型链上。
注意当这样设置后,方法一依然会判断出arr2不是数组 但是方法二会误判 把arr2当做数组;
那这个时候该怎么办呢?
方法三:判断对象的内部class属性
每个对象内部都有一个class属性,用来记录该对象创建时的数据类型,不会随继承关系而改变类型。
但是class有两个问题。
问题一:class是内部属性 只有最顶层的Object.prototype.toString()才能输出对象的class属性。
例如 Object.prototype.toString(arr2) 输出结果为[object String]。
第一个参数表示是一个对象,第二个参数表示是对象的类型。
但是这个时候你会发现上面输出结果并不是[object String],而是[object Object]。这是为什么呢?
事实上,这是因为js对象中的多态。
关于多态:在js中同一个函数在不同情况下表现出不同的状态。如果子对象觉得父对象的成员不好用,可在本地定义同名成员,覆盖父对象中继承来的成员。以用来体现子对象和父对象之间的差异。
另外一个知识点:内置类型的原型对象中几乎都重写了新的toString()。这就是为什么上面不会输出[object String]。因为String.prototype中已经有重写过的toString,覆盖了顶级原型对象中的toString()。因此输出结果不是预料的那样。
那该怎么调用顶级对象中的toString()方法呢?
这个时候有一个逆天的call()方法出来了!
Object.prototype.toString.call(arr2)==[object String];
用法:要调用的函数.call(对象);把对象放在参数中,强行调用call前的方法。
这样子,就可以判断出一个变量创建时是否是数组了,例如
Object.prototype.toString.call(arr2)=="[object Array]" 结果是false;
Object.prototype.toString.call(arr1)=="[object Array] "结果是true;
方法四:用isArray
Array.isArray(arr1) 返回一个布尔值;
但是有一个问题isArray是es5中的内容 ie9以下不支持,如何解决兼容性?
if(!("is Array" in Array)){
Array.isArray=function(obj){
return Object.prototype.toString.call(obj)==[object Array]
}
}
Array.isArray(arr1)
结果为true。