数组是编程语言中最基本而且重要的数据结构
在我们JavaScript中,数组是特殊的对象
有时候我们就会遇到判断数组的问题
今天这里整理一下哪些方法能够判断一个变量是否是数组
instanceof
var arr = [1,2,3];
console.log(arr instanceof Array);//true
instanceof运算符会检测arr是否继承自Array.prototype
看起来没什么问题,确实返回true,证实了arr是数组
这种方法确实能检测出大部分数组,但是某种情况无法检测
一会儿我们再来讨论
constructor
数组的原型中一定存在constructor保存着它的构造器Array
var arr = [1,2,3];
console.log(arr.constructor === Array);//true
和上面的方法一样,看似无懈可击,实则不能检测某种特例
Object.prototype.toString
这个方法会获取对象内部的属性[[class]],然后返回你一个字符串
利用顶级原型的属性,再利用call,可以达到我们检测数组的目的
一起来看一下
var arr = [1,2,3];
console.log(Object.prototype.toString.call(arr) === '[object Array]');//true
虽然Array也继承自Obejct,但是它内部重写了toString,我们无法用它判断类型
Array.isArray
var arr = [1,2,3];
console.log(Array.isArray(arr));//true
大部分浏览器内置Array内部实现了isArray判断数组的方法
少数低版本浏览器没有,比如IE8及以下版本
问题分析
所以要是不考虑兼容问题的话,Array.isArray可以检测数组没问题
Object.prototype.toString是最无懈可击的方法
下面我们来看看instanceof和constructor的缺点
它们的缺点就是在多窗口和多框架的web页面中兼容不好
做一个实验
我在服务器上挂在了子页面并声明了一个数组
/child.html
var arr = [1,2,3];
然后挂载父页面通过iframe标签引入子页面
var frame = document.getElementsByTagName('iframe')[0];
document.onclick = function(){
var array = frame.contentWindow.arr;
console.log(array instanceof Array);//false
console.log(array.constructor === Array);//false
console.log(Array.isArray(array));//true
console.log(Object.prototype.toString.call(array) === '[object Array]');//true
}
点击页面发现了问题
其中一个框架页面中的数组不是另一个框架页面的Array()构造函数的实例
instanceof和constructor方法都不好用了
而Array.isArray和Object.prototype.toString却表现的很好
我们来封装一个完美的函数
function myIsArray(value){
if(Array.isArray){
return Array.isArray(value);
}else{
return Object.prototype.toString.call(value) === '[object Array]';
}
}
总结
判断数组的方法
arr instanceof Array【不能跨页面判断】
arr.constructor === Array【不能跨页面判断】
Array.isArray(arr)【兼容问题】
Object.prototype.toString.call(arr)