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]]屬性,十分穩定,因此能夠信任對象