4

SLife博客-Web前端学习分享

 3 years ago
source link: https://my.oschina.net/simplelife1989/blog/5007303
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Javascript如何判断是否是数组的四种方法? - SLife博客-Web前端学习分享 - OSCHINA - 中文开源技术交流社区

一、通过instanceof判断:返回一个布尔值

let a = [];
a instanceof Array; //true
let b = {};
b 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 Arraytrue,须保证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

三、通过Object.prototype.toString.call()判断:返回'[object Array]'

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

//检验是否为数组
let a = [1,2,3]
Object.prototype.toString.call(a) === '[object Array]';//true
//检验是否是函数
let b = function () {};
Object.prototype.toString.call(b) === '[object Function]';//true
//检验是否是数字
let c = 1;
Object.prototype.toString.call(c) === '[object Number]';//true
//检验是否为对象
let d = {};
Object.prototype.toString.call(d) === '[object Object]' //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

四、通过Array.isArray()判断:返回一个布尔值

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

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

简单好用,且对于多全局环境,Array.isArray() 同样能准确判断,

  • Array.isArray() 是在ES5中提出,可能会存在ES5之前不支持此方法的情况
  • 解决方法

配合Object.prototype.toString().call()进行封装

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

最终推荐Array.isArray()方法

  • 从ES5新增isArray()方法正是为了提供一个稳定可用的数组判断方法
  • 对于ES5之前不支持此方法的问题,我们可以做好兼容进行自行封装

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK