如何检测变量是否为数组 [英] How to detect if a variable is an array

查看:39
本文介绍了如何检测变量是否为数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

确定 JavaScript 中的变量是否为数组的最佳事实标准跨浏览器方法是什么?

What is the best de-facto standard cross-browser method to determine if a variable in JavaScript is an array or not?

在网上搜索有许多不同的建议,有些是好的,有些是无效的.

Searching the web there are a number of different suggestions, some good and quite a few invalid.

例如,下面是一个基本的方法:

For example, the following is a basic approach:

function isArray(obj) {
    return (obj && obj.length);
}

但是,请注意如果数组为空会发生什么,或者 obj 实际上不是数组而是实现了长度属性等.

However, note what happens if the array is empty, or obj actually is not an array but implements a length property, etc.

那么,就实际工作、跨浏览器和仍然高效执行而言,哪种实现是最好的?

So which implementation is the best in terms of actually working, being cross-browser and still perform efficiently?

推荐答案

JS中对象的类型检查是通过instanceof完成的,即

Type checking of objects in JS is done via instanceof, ie

obj instanceof Array

如果对象跨帧边界传递,这将不起作用,因为每个帧都有自己的 Array 对象.您可以通过检查对象的内部 [[Class]] 属性来解决此问题.要获得它,请使用 Object.prototype.toString()(ECMA-262 保证可以正常工作):

This won't work if the object is passed across frame boundaries as each frame has its own Array object. You can work around this by checking the internal [[Class]] property of the object. To get it, use Object.prototype.toString() (this is guaranteed to work by ECMA-262):

Object.prototype.toString.call(obj) === '[object Array]'

这两种方法都只适用于实际数组,而不适用于类似数组的对象,例如 arguments 对象或节点列表.由于所有类似数组的对象都必须有一个数字 length 属性,我会像这样检查这些:

Both methods will only work for actual arrays and not array-like objects like the arguments object or node lists. As all array-like objects must have a numeric length property, I'd check for these like this:

typeof obj !== 'undefined' && obj !== null && typeof obj.length === 'number'

请注意,字符串将通过此检查,这可能会导致问题,因为 IE 不允许通过索引访问字符串的字符.因此,您可能希望将 typeof obj !== 'undefined' 更改为 typeof obj === 'object' 以排除具有不同于 'object' 全部.这仍然会让字符串对象通过,必须手动排除.

Please note that strings will pass this check, which might lead to problems as IE doesn't allow access to a string's characters by index. Therefore, you might want to change typeof obj !== 'undefined' to typeof obj === 'object' to exclude primitives and host objects with types distinct from 'object' alltogether. This will still let string objects pass, which would have to be excluded manually.

在大多数情况下,您真正​​想知道的是您是否可以通过数字索引迭代对象.因此,检查对象是否具有名为 0 的属性可能是个好主意,这可以通过以下检查之一完成:

In most cases, what you actually want to know is whether you can iterate over the object via numeric indices. Therefore, it might be a good idea to check if the object has a property named 0 instead, which can be done via one of these checks:

typeof obj[0] !== 'undefined' // false negative for `obj[0] = undefined`
obj.hasOwnProperty('0') // exclude array-likes with inherited entries
'0' in Object(obj) // include array-likes with inherited entries

转换为对象对于类数组原语(即字符串)正确工作是必要的.

The cast to object is necessary to work correctly for array-like primitives (ie strings).

以下是对 JS 数组进行稳健检查的代码:

Here's the code for robust checks for JS arrays:

function isArray(obj) {
    return Object.prototype.toString.call(obj) === '[object Array]';
}

和可迭代(即非空)类数组对象:

and iterable (ie non-empty) array-like objects:

function isNonEmptyArrayLike(obj) {
    try { // don't bother with `typeof` - just access `length` and `catch`
        return obj.length > 0 && '0' in Object(obj);
    }
    catch(e) {
        return false;
    }
}

这篇关于如何检测变量是否为数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆