数组类型检测

758 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动

数组是我们日常开发离不开的,判断一个数据类型是否为数组也是一件十分常见的事情,那么如果让你判断一个数据是否为数组,此时的你能想到几种方式呢?各自又有什么用的优缺点呢?

接下来便一起看看吧

typeof

相信很多人在脑中快速搜索答案时,typeof应该是最容易想到的数据类型判断的方式

对于 Function、String、Number、Undefined 等几种类型的对象来说,typeof完全没有压力的可以胜任

typeof 1; // 'number'
typeof '1'; // 'string'
typeof undefined; // 'undefined'
typeof true; // 'boolean'
typeof Symbol(); // 'symbol'
typeof null; // 'object'
const fn = () => {};
typeof fn; // 'function'

但是在上述之外的数据类型检测时,typeof就显得力不从心了

typeof null // 'object'
typeof [] // 'object'
typeof {} // 'object'

可以发现使用typeof类型检测结果均为object,而数组恰恰在此之列

结论:typeof虽然可以判断基础数据类型(null 除外),但是引用数据类型中,除了 function 类型以外,其他的也无法判断

Instanceof

想必 instanceof 的方法大家也不会陌生,我们 new 一个对象,那么这个新对象就是它原型链继承上面的对象了,通过 instanceof 我们能判断这个对象是否是之前那个构造函数生成的对象,这样就基本可以判断出这个新对象的数据类型

判断引用数据类型

class Animal{}
const animal = new Animal();
console.log(animal instanceof Animal); // true

const newNum = new Number(12);
console.log(newNum instanceof Number); // true

const arr = [1, 2] // 等价于 new Array(1, 2)
console.log(arr instanceof Array); // true

判断基础数据类型

let num = 123;
console.log(num instanceof Number); // false

结论:instanceof 可以准确地判断复杂引用数据类型,但是不能正确判断基础数据类型

constructor

在JS中,每个对象都有一个constructor属性,它引用了初始化该对象的构造函数,一般情况下,除了 undefinednull,其它都能使用 constructor 判断类型

const arr = [];
console.log(arr.constructor === Array); // true

但是由于JS的灵活性,导致其在有些时候是不准确的,比如我们可以人为的修改constructor

const arr = [];
arr.constructor = Object; 
console.log(arr.constructor === Array); // false

Object.prototype.toString

toString 是 Object 的原型方法,调用该方法,可以统一返回格式为 “[object 数据类型]” 的字符串

对于 Object 对象,直接调用 toString() 就能返回 [object Object];而对于其他对象,则需要通过 call 来调用,才能返回正确的类型信息

Object.prototype.toString({})       // "[object Object]"
Object.prototype.toString.call([])  //"[object Array]"
Object.prototype.toString.call('1') // "[object String]"

结论:点用toString方法判断数据类型,可以很稳定的得到期望的类型检测结果,适用于全部数据类型

Array.isArray

Array.isArray是ES标准提供的一个方法

Array.isArray([]) // true
Array.isArray(1) // false

结论:ES标准提供,弊端是存在兼容性问题