一、前言

如何判断一个对象或一个值是否是数组或者对象,是我们在工作和面试中会经常碰到的一个问题,下面我们来讨论一下这几种情况:

二、判断对象是否是数组的几种方式

1、通过instanceof判断
instanceof运算符用于检验构造函数的prototype属性是否出现在对象的原型链中的任何位置,返回一个布尔值。

let a = [];
a instanceof Array; // true
let b = {};
b instanceof Array; // false

在上方代码中,instanceof运算符检测Array.prototype属性是否存在于变量a的原型链上,显然a是一个数组,拥有Array.prototype属性,所以为true。
存在问题:
需要注意的是,prototype属性是可以修改的,所以并不是最初判断为true就一定永远为true。其次,当我们的脚本拥有多个全局环境,例如html中拥有多个iframe对象,instanceof的验证结果可能不会符合预期,例如:

//为body创建并添加一个iframe对象
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
// 获取iframe对象的构造数组方法
xArray = window.frames[0].Array;
// 通过构造函数获取一个实例
var arr = new xArray(1, 2, 3);
arr.instanceof Array; // false

导致这种问题是因为iframe会产生新的全局环境,它也会拥有自己的Array.prototype属性,让不同环境下的属性相同很明显是不安全的做法,所以Array.prototype !== window.frames[0].Array.prototype,想要arr instanceof Array为true.你得保证arr是由原始Array构造函数创建时才可行。

通过constructor判断

我们知道,实例的构造函数constructor指向构造函数,那么通过constructor属性也可以判断是否为一个数组。

let a = [1, 3, 4];
a.constructor === Array; // true

同样,这种判断也会存在多个全局环境的问题,导致的问题与instanceof相同。

// 为body创建并添加一个iframe标签
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
// 取得iframe对象的构造数组方法
xArray = window.frames[window.frames.length - 1].Array;
// 通过构造函数获取一个实例
var arr = new xArray (1, 2, 3);
arr.constructor === Array; // false

3、通过Object.prototype.toString.call()判断

Object.prototype.toString().call可以获取到对象的不同类型。例如

let a = [1, 2, 3];
Object.prototype.toString.call(a) === '[object Array]'; // true

它强大的地方在于不仅仅可以检验是否为数组,比如是否是一个函数,是否是数字等等

// 检验是否是函数
let a = function() {};
Object.prototype.toString().call(a) === '[object Function]'; // true
// 检验是否是数字
let b = 1;
Object.prototype.toString.call(a) === '[object Number]'; // true

甚至对于多全局环境时,Object.prototype.toString().call()也能符合预期处理判断。

// 为body创建并添加一个iframe标签
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
//取得iframe对象的构造数组方法
xArray = window.frames[window.frames.length-1].Array;
//通过构造函数获取一个实例
var arr = new xArray(1,2,3); 
console.log(Object.prototype.toString.call(arr) === '[object Array]');//true

4、通过Array.isArray()判断

Array.isArray用于确定传递的值是否是一个数组,返回一个布尔值。

let a = [1, 2, 3];
Array.isArray(a); // true

简单好用,而且对于多全局环境,Array.isArray()同样能准确判断,但有个问题,Array.isArray()是在ES5中提出的,也就是说ES5之前可能会存在不支持此方法的情况。怎么解决呢???

三、判断数组方法的最终推荐

当然还是用Array.isArray, 从ES5新增isArray()方法正是为了提供一个稳定可用的数组判断方法,不可能专门为此提供出的好东西不用,而对于ES5之前不支持此方法的问题,我们其实可以做好兼容进行自行封装,像这样:

if (!Array.isArray) {
	Array.isArray = function(arg) {
		return Object.prototype.toString.call(arg) === '[object, Array]';
	}
}

以上就是我想说的几组判断是否是数组的方法

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐