js数组检测

数组检测

检测constructor

v.constructor === Array

缺点:

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)

缺点:

可能存在使用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]]属性导致检测失效行为

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规范细节

小结

从以ducktype检测对象的数字索引、constructor、instanceof、toString方法来看,它们都在一定程度上是不可信任的,也就是会可能被人篡改导致检测异常,而isArray检测的是内部的[[Class]]属性,十分稳定,所以可以信任

posted @ 2019-05-15 16:00  兴趣使然的Geek  阅读(193)  评论(0编辑  收藏  举报