问题描述
确定 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;
}
}
这篇关于如何检测变量是否为数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!