JavaScript有五种方法可以确定一个值到底是什么类型,分别是typeof运算符,constructor法,instanceof运算符,Object.prototype.toString方法以及Array.isArray法.
1.用typeof运算符来判断(判断数组这里无效)
typeof是javascript原生提供的判断数据类型的运算符,它会返回一个表示参数的数据类型的字符串,例如:
const s = 'hello';console.log(typeof(s))//String
以下是我在MDN的文档中找到的一张包含typeof运算法的针对不同参数的输出结果的表格:
从这张表格可以看出,数组被归到了Any other object当中,所以typeof返回的结果应该是Object,并没有办法区分数组,对象,null等原型链上都有Object的数据类型。
const a = null;const b = {};const c= [];console.log(typeof(a)); //Objectconsole.log(typeof(b)); //Objectconsole.log(typeof(c)); //Object
运行上面的代码就会发现,在参数为数组,对象或者null时,typeof返回的结果都是object,可以使用这种方法并不能识别出数组,因此,在JavaScript项目中用typeof来判断一个位置类型的数据是否为数组,是非常不靠谱的。
方法一:isArray()数组自带的判断方法
let a =[1,2,3];
Array.isArray(a); //true
方法二:instanceof操作符
let a = [1,2,3];
a instanceof Array; //true
方法三:constructor.toString()方法
let a = [1,2,3]
//把constructor转换成字符串,然后通过indexOf去判断是否包含Array
a.constructor.toString().indexOf("Array") !== -1; //true
const a = [];console.log(a.constructor);//function Array(){ [native code] }
const a = [];console.log(a.constructor == Array);//true
方法四:Object.prototype.toString.call(a).indexOf(“Array”)
let a = [1,2,3];
//和上面一个意思,都是转换成字符串,然后判断是否包含Array,
//有就会返回下标位置
/*
Object.prototype.toString会取对象的一个内部属性[[Class]],
大概会返回一个类似于"[object Array]"这样的字符串,注意,
这里这个是内部属性,外部是无法访问的,然后再配合call方法,
改变toString的this指向,也就是指向a数组
*/
Object.prototype.toString.call(a).indexOf("Array")
4.用Object的toString方法判断
另一个行之有效的方法就是使用Object.prototype.toString方法来判断,每一个继承自Object的对象都拥有toString的方法。
如果一个对象的toString方法没有被重写过的话,那么toString方法将会返回"[objecttype]",其中的type代表的是对象的类型,根据type的值,我们就可以判断这个疑似数组的对象到底是不是数组了。
你可能会纠结,为什么不是直接调用数组,或则字符串自己的的toString方法呢?我们试一试就知道了。
const a = ['Hello','Howard'];const b = {0:'Hello',1:'Howard'};const c = 'Hello Howard';a.toString();//"Hello,Howard"b.toString();//"[object Object]"c.toString();//"Hello,Howard"
从上面的代码可以看出,除了对象之外,其他的数据类型的toString返回的都是内容的字符创,只有对象的toString方法会返回对象的类型。所以要判断除了对象之外的数据的数据类型,我们需要“借用”对象的toString方法,所以我们需要使用call或者apply方法来改变toString方法的执行上下文。
const a = ['Hello','Howard'];const b = {0:'Hello',1:'Howard'};const c = 'Hello Howard';Object.prototype.toString.call(a);//"[object Array]"Object.prototype.toString.call(b);//"[object Object]"Object.prototype.toString.call(c);//"[object String]"
使用apply方法也能达到同样的效果:
const a = ['Hello','Howard'];const b = {0:'Hello',1:'Howard'};const c = 'Hello Howard';Object.prototype.toString.apply(a);//"[object Array]"Object.prototype.toString.apply(b);//"[object Object]"Object.prototype.toString.apply(c);//"[object String]"
总结一下,我们就可以用写一个方法来判断数组是否为数组:
const isArray = (something)=>{return Object.prototype.toString.call(something) === '[object Array]';}cosnt a = [];const b = {};isArray(a);//trueisArray(b);//false