ES5和ES6中,都怎么判断变量是否为数组?

JS的弱类型机制致使判断变量类型是初级前端开发者面试时的必考题,通常我都会将其做为考察候选人第一题,而后基于此展开。javascript

在ES5中判断变量是否为数组

在ES5中,咱们至少有以下5种方式去判断一个值是否数组:html

var a = []; 
// 1.基于instanceof 
a instanceof Array; 
// 2.基于constructor 
a.constructor === Array; 
// 3.基于Object.prototype.isPrototypeOf 
Array.prototype.isPrototypeOf(a); 
// 4.基于getPrototypeOf 
Object.getPrototypeOf(a) === Array.prototype; 
// 5.基于Object.prototype.toString 
Object.prototype.toString.apply(a) === '[object Array]';
复制代码

以上,除了Object.prototype.toString外,其它方法都不能正确判断变量的类型。前端

要知道,代码的运行环境十分复杂,一个变量可能使用浑身解数去迷惑它的创造者。且看:java

var a = {
    __proto__: Array.prototype
}; 
// 分别在控制台试运行如下代码 
// 1.基于instanceof 
a instanceof Array; // => true 
// 2.基于constructor 
a.constructor === Array; // => true 
// 3.基于Object.prototype.isPrototypeOf 
Array.prototype.isPrototypeOf(a); // => true 
// 4.基于getPrototypeOf 
Object.getPrototypeOf(a) === Array.prototype; // => true
复制代码

以上,4种方法将所有返回true,为何呢?咱们只是手动指定了某个对象的__proto__属性为Array.prototype,便致使了该对象继承了Array对象,这种绝不负责任的继承方式,使得基于继承的判断方案瞬间土崩瓦解。web

不只如此,咱们还知道,Array是堆数据,变量指向的只是它的引用地址,所以每一个页面的Array对象引用的地址都是不同的。iframe中声明的数组,它的构造函数是iframe中的Array对象。若是在iframe声明了一个数组x,将其赋值给父页面的变量y,那么在父页面使用y instanceof Array ,结果必定是false的。�而最后一种返回的是字符串,不会存在引用问题。实际上,多页面或系统之间的交互只有字符串可以畅行无阻。面试

鉴于上述的两点缘由,故笔者推荐使用最后一种方法去撩面试官(别提是我说的),若是你还不信,这里刚好有篇文章跟我持有相同的观点:Determining with absolute accuracy whether or not a JavaScript object is an array数组

在ES6中判断变量是否为数组

鉴于数组的经常使用性,在ES6中新增了Array.isArray方法,使用此方法判断变量是否为数组,则很是简单,以下:app

Array.isArray([]); // => true 
Array.isArray({0: 'a', length: 1}); // => false
复制代码

实际上,经过Object.prototype.toString去判断一个值的类型,也是各大主流库的标准。所以Array.isArray的polyfill一般长这样:函数

if (!Array.isArray){ 
    Array.isArray = function(arg){ 
        return Object.prototype.toString.call(arg) === '[object Array]'; 
    }; 
}复制代码
相关文章
相关标签/搜索