1. 犀牛前端部落首页
  2. Javascript百科

如何用js检查对象是否是一个数组

今天俺跟大家分享一下js中如何检查一个对象是数组,有些新手同学可能会觉得直接用typeof不就行了吗,哈哈哈…大家可以试试typeof 数组返回的是啥呢?

想要阅读js检查对象的内容可以看我这篇文章

现代浏览器解决方案

如果不考虑老浏览器,仅考虑现在的浏览器,我们可以使用ES5的语法,如下代码:

/**
 * 时间:2019年8月16日
 * 前端教程: https://www.pipipi.net/
 */
Array.isArray(obj);

该方法兼容Chrome 5, Firefox 4.0, IE 9, Opera 10.5 和 Safari 5,详细兼容性,可以查阅这篇文章

为了考虑兼容性,你还可以添加以下代码:

/**
 * 时间:2019年8月16日
 * 前端教程: https://www.pipipi.net/
 */
if (typeof Array.isArray === 'undefined') {
  Array.isArray = function(obj) {
    return Object.prototype.toString.call(obj) === '[object Array]';
  }
};

如果你使用jQuery,可以使用jQuery.isArray(obj)或$ .isArray(obj)。

其他解决方案

数组是一个对象(typeof [] ===“object”),但与传统对象不同,它们有一个length属性(typeof({}).length ===“undefined”)。 null也是一个对象(typeof null ===“object”),但是由于null不是对象,因此无法访问null属性。这是规范中的一个错误,一直回到JavaScript的设计开始,关于这个介绍可以查看我的这篇文章( typeof JavaScript基础:typeof null 为什么返回”object”)。

不幸的是,这并不考虑[] vs {length:0}。所以我们现在必须转向原型链。

以下是完整代码:

/**
 * 时间:2019年8月16日
 * 前端教程: https://www.pipipi.net/
 */
function is_array(array){
    return array !== null
        && typeof array === "object"
        && array.__proto__ === Array.prototype;
}

[ [], [1,2,3], {length: 0}, {},
  1, 0, Infinity, NaN, "1", "[1,2,3]",
  null, undefined, [null], [undefined], {a:[]},
  [{}], [{length: 0}], [Infinity], [NaN],
  {__proto__: Array.prototype}
].filter(is_array)
// 期待结果: [ [], [1,2,3], [null], [undefined], [{}], [{length: 0}], [Infinity], [NaN] ]
// 实际结果:   [ [], [1,2,3], [null], [undefined], [{}], [{length: 0}], [Infinity], [NaN], {__proto__: Array.prototype} ]

接下来我们再看一个例子,我们创造一个恶意修改像数组的对象来达到通过测试的目的,将对象的__proto__改成数组的Array.prototype可以达成这种效果。

/**
 * 时间:2019年8月16日
 * 前端教程: https://www.pipipi.net/
 */
a = {__proto__: Array.prototype}; // Array {}
a.push(5)
a // [5]
a.length = 5
a // [5, empty x 4]
b = a.map(n => n*n) // [25, empty x 4]
b.push(undefined)
b.push(undefined)
b // [25, empty x 4, undefined, undefined]
b[1] // undefined
b[1] === b[5] // true
Array.isArray(a) // false
is_array(a)//true
Array.isArray(b) // true

可以看到,我们写的函数虽然返回了ture但是实际上a并不是true,因此可以有效判断对象是否是一个数组的方法只有,Array.isArray方法。

我个人认为开发者应该鼓励用户使用新版的浏览器,来避免产生一些不必要的麻烦, 并且如果支持旧的JS版本意味着支持旧浏览器意味着鼓励使用不安全的软件也会让用户面临软件带来的安全风险。

原创文章,作者:犀牛前端部落,如若转载,请注明出处:https://www.pipipi.net/2238.html

发表评论

登录后才能评论