判断变量是否是数组?

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。

你可能感兴趣的:(判断变量是否是数组?)