Bootstrap

js 判断变量是否为数组的方法以及各自利弊

1.说明

判断一个变量或者参数是否为数组,相信大家工作和面试中都会遇到,今天和大家交流下心得

2.判断变量是否是数组的几种方式

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

let arr = [];
arr instanceof Array; //true
let object = {};
object instanceof Array; //false

在上方代码中,instanceof运算符检测Array.prototype属性是否存在于变量a的原型链上,显然a是一个数组,拥有Array.prototype属性,所以为true。

缺点:需要注意的是,prototype属性是可以修改的,所以并不是最初判断为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构造函数创建时才可行。

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

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

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

(3)通过Object.prototype.toString.call()判断
Object.prototype.toString().call()可以获取到对象的不同类型,例如

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

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

//检验是否是函数
let func = function () {};
Object.prototype.toString.call(func) === '[object Function]';//true
//检验是否是数字
let num = 1;
Object.prototype.toString.call(num) === '[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 arr = ['你','我','他']
Array.isArray(arr);//true

简单好用,es5新提出的方法,而且不用🤔环境问题

3.总结

哪个好用,当然还是Array.isArray(arr),因为是专业的,es5专门用来检测数组的,如果支持es5语法,请自行兼容封装qwq,👌。

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

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;