前言
我们在日常开发中,常常有判断某值的需求,今天我们总结一下常见的几种用来判断是否为数组的JavaScript方法。
Array.isArray
Array.isArray()是ES5新增的方法,用于确定传递的值是否是一个数组,如果是数组,则返回true,否则返回false。
letarr=[];console.log(Array.isArray(arr));//true
下面的函数调用都返回true:
Array.isArray([]);Array.isArray([1]);Array.isArray(newArray());Array.isArray(newArray("a","b","c","d"));
需要注意的一点是:其实Array.prototype也是一个数组。
Array.isArray(Array.prototype);//true
下面的函数调用都返回false:
Array.isArray();Array.isArray({});Array.isArray(null);Array.isArray(undefined);Array.isArray(17);Array.isArray('Array');Array.isArray(true);Array.isArray(false);Array.isArray(newUint8Array(32))Array.isArray({__proto__:Array.prototype});
兼容性如下图:
可以看到,新版的主流浏览器都是支持该方法的,可以放心使用。
constructor
Object的每个实例都有构造函数constructor,用于保存着用于创建当前对象的函数
letarr=[];console.log(arr.constructor===Array);//true
需要注意的是,constructor有被修改的风险,判断结果不一定准确,比如:
letarr=[1,2,3];arr.constructor=function(){}console.log(arr.constructor===Array);//false
一般不推荐使用constructor来判断是否为数组,我们只需要知道有这么一个方法就行。
instanceof
instanceof运算符用于检测构造函数的prototype属性是否出现在某个实例对象的原型链上。举个例子:
//定义构造函数functionC(){}functionD(){}varo=newC();oinstanceofC;//true,因为Object.getPrototypeOf(o)===C.prototypeoinstanceofD;//false,因为D.prototype不在o的原型链上oinstanceofObject;//true,因为Object.prototype.isPrototypeOf(o)返回trueC.prototypeinstanceofObject;//true,同上
用instanceof来判断是否为数组的用法如下:
letarr=[];console.log(arrinstanceofArray);//true
使用instanceof需要注意两点:
- 构造函数的prototype和实例的原型链都有可能会改变,所以判断出的结果不一定一成不变。
- 在有iframe的页面脚本中使用instanceof,可能会得到错误的结果,因为iframe拥有独立的全局环境,不同的全局环境拥有不同的全局对象,从而拥有不同的内置类型构造函数。
isPrototypeOf
isPrototypeOf()可以用于测试一个对象是否存在于另一个对象的原型链上。用法如下:
functionFoo(){}functionBar(){}functionBaz(){}Bar.prototype=Object.create(Foo.prototype);Baz.prototype=Object.create(Bar.prototype);varbaz=newBaz();console.log(Baz.prototype.isPrototypeOf(baz));//trueconsole.log(Bar.prototype.isPrototypeOf(baz));//trueconsole.log(Foo.prototype.isPrototypeOf(baz));//trueconsole.log(Object.prototype.isPrototypeOf(baz));//true
如果要用isPrototypeOf来判断传入参数是否为数组,可以这样用:
letarr=[];console.log(Array.prototype.isPrototypeOf(arr));//true
Object.prototype.toString
每个对象都有一个toString()方法,当该对象被表示为一个文本值时,或者一个对象以预期的字符串方式引用时自动调用。
默认情况下,toString()方法被每个Object对象继承。如果此方法在自定义对象中未被覆盖,toString()返回"[objecttype]"字符串,其中type是对象的类型。
可以通过toString()来获取每个对象的类型。为了每个对象都能通过Object.prototype.toString()来检测,需要以Function.prototype.call()或者Function.prototype.apply()的形式来调用,传递要检查的对象作为第一个参数,称为thisArg。用法如下:
Array.isArray([]);Array.isArray([1]);Array.isArray(newArray());Array.isArray(newArray("a","b","c","d"));0
如果要用来判断一个对象是否为数组,可这样使用:
Array.isArray([]);Array.isArray([1]);Array.isArray(newArray());Array.isArray(newArray("a","b","c","d"));1
兼容性如下:
typeof
说到判断类型,可能很多人都会想到typeof方法,我们这里来复习一下typeof相关内容。
typeof操作符返回一个字符串,表示未经计算的操作数的类型。
Array.isArray([]);Array.isArray([1]);Array.isArray(newArray());Array.isArray(newArray("a","b","c","d"));2
typeof可能的返回值如下:
通过上图可以看到,数组对象属于“其他任何对象”,所以数组对象的typeof返回值是“object”:
Array.isArray([]);Array.isArray([1]);Array.isArray(newArray());Array.isArray(newArray("a","b","c","d"));3
所以,我们要尽量避免使用typeof。
总结
以上就是几种用来判断一个值是否为数组的几种方法,当然有好用的也有不好用的,但是不管怎样,我们知道有这么回事总归是好的。总结一下:
- 最好用的方法是Array.isArray,只是不支持IE8及以下。
- 如果要考虑兼容性,则可以使用Object.prototype.toString。