- Javascript类型判断的坑
类型在Javascript中一直是一个很薄弱的概念,也一直缺少能够准确判断类型的方法。
那我们怎么来准确的判断一个变量是否真的是数组呢?
- typeof吗?
let arr = [];
// true
typeof arr === 'object';
// false
typeof arr === 'array';
所以typeof只能辅助我们做一些判断,但是不能完全依赖它。
- instanceof吗?
let arr = [];
const w = window.open('about:blank');
// false
arr instanceof w.Array;
let o = {};
Object.setPrototypeOf(o, Array.prototype);
// true
o instanceof Array;
当多个页面的实例(可能是窗口之间也可能是frame)之间通信时,instanceof可能不会像我们预期的那样工作。
也可以骗过instanceof,只要把Array.prototype放到被检测对象的原型链上即可。
- Object.prototype.toString.call
该方法相对靠谱
let arr = [];
// true
Object.prototype.toString.call(arr) === '[object Array]'
let o = {};
Object.setPrototypeOf(o, Array.prototype);
// true
Object.prototype.toString.call(o) === '[object Object]'
class C extends Array {}
let a = new C();
// true
Object.prototype.toString.call(a) === '[object Array]'
但是也有弊端:
- 此方法并不是语言设计用来判断类型的,只是它返回了内部的class名称,恰好能够达到类型判断的目的。说白了就是一个hack
- 由于不是语言的设计初衷,因此长期来看,它还是不太靠谱。ES6中,添加了Symbol.toStringTag,只需要给对象添加该属性,Object的toString便会参考该值,返回自定义的String,请看下面的例子
let o = {[Symbol.toStringTag]: 'Array'};
// true
Object.prototype.toString.call(o) === '[object Array]'
因此在ES6越来越普及的未来,该方法也越来越不可信了。
- Array.isArray
此方法专门用来解决不能准确判断数组类型的问题。
如果你想知道某个变量是否真的是数组,请使用此方法。上面方法的缺陷在此方法上均不存在。
此方法是ES5的方法,chrome和safari第5版便已经实现,IE9也实现了此方法。
因此移动端可以放心使用此方法,PC端如果不考虑IE8,也可以放心使用。