v.constructor === Array
缺点:es6
let arr = [] console.log(arr.constructor === Array); // true 在子类中定义constructor属性,屏蔽原型上的constructor致使检测出错 arr.constructor = Object console.log(arr.constructor === Array); // false 改写原型上的constructor,致使检测出错 Array.prototype.constructor = {} console.log(arr.constructor === Array); // false
v instanceof Array
缺点:数组
覆盖整个数组原型,然而规范对其属性描述为{ [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false},就是不能覆盖的意思 let arr = [] console.log(arr.constructor === Array); // true Array.prototype = {} console.log(arr instanceof Array); // true 跨iframe的数组,原型不共享,致使instanceof检测失效 var iframe = document.createElement('iframe'); document.body.appendChild(iframe); xArray = window.frames[window.frames.length-1].Array; var arr = new xArray(1,2,3) arr instanceof Array; // false
Object.prototype.toString.call(v)
缺点:app
可能存在使用Symbol.toStringTag重写toString行为,致使检测失效,这里的重写是指将[object class] 中的class重写为指定值,其默认值为\[[Class]] let arr = [] console.log(Object.prototype.toString.call(arr) === "[object Array]"); Array.prototype[Symbol.toStringTag] = "11" // [object 11] console.log(Object.prototype.toString.call(arr) === "[object Array]");
优势:解决了以上iframe原型共享检测失效问题以及重写[[Class]]属性致使检测失效行为prototype
Array.isArray(v) var iframe = document.createElement('iframe'); document.body.appendChild(iframe); xArray = window.frames[window.frames.length-1].Array; var arr = new xArray(1,2,3) arr instanceof Array; // false Array.isArray(arr) // true let arr = [] console.log(Object.prototype.toString.call(arr) === "[object Array]"); // true Array.prototype[Symbol.toStringTag] = "11" // [object 11] console.log(Object.prototype.toString.call(arr) === "[object Array]"); // false Array.isArray(arr) // true
Array.isArray规范细节
code
从以ducktype检测对象的数字索引、constructor、instanceof、toString方法来看,它们都在必定程度上是不可信任的,也就是会可能被人篡改致使检测异常,而isArray检测的是内部的[[Class]]属性,十分稳定,因此能够信任对象