js數組檢測

數組檢測

檢測constructor

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輸出[[Class]]的默認行爲

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]");

ES6

優勢:解決了以上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]]屬性,十分穩定,因此能夠信任對象

相關文章
相關標籤/搜索