如何检查变量是否是javascript中的数组?

How do you check if a variable is an array in JavaScript?

本问题已经有最佳答案,请猛点这里访问。

我想检查一个变量是数组还是javascript中的单个值。

我找到了一个可能的解决办法…

1
if (variable.constructor == Array)...

这是最好的方法吗?


有几种方法可以检查变量是否是数组。最好的解决方案就是你选择的那个。

1
variable.constructor === Array

这是Chrome上最快的方法,很可能是所有其他浏览器。所有数组都是对象,因此检查构造函数属性对于JavaScript引擎来说是一个快速的过程。

如果在确定对象属性是否为数组时遇到问题,必须首先检查该属性是否存在。

1
variable.prop && variable.prop.constructor === Array

其他一些方法是:

1
variable instanceof Array

此方法的运行速度约为第一个示例的1/3。如果你只关注漂亮的代码,而不太关注性能的话,它仍然很可靠,看起来更干净。注意,检查数字不起作用,因为variable instanceof Number总是返回false。更新:instanceof现在的速度是2/3!

1
Array.isArray(variable)

在我看来,最后一个是最丑的,也是最慢的。以1/5左右的速度运行为例。array.prototype实际上是一个数组。您可以在这里阅读更多关于它的信息:https://developer.mozilla.org/en-us/docs/web/javascript/reference/global_objects/array/isarray

所以还有另一个更新

1
Object.prototype.toString.call(variable) === '[object Array]';

这家伙是最慢的尝试检查阵列。然而,这是一站式商店,任何类型的你正在寻找。但是,由于您要查找数组,所以只需使用上面最快的方法。

另外,我还运行了一些测试:http://jspef.com/instanceof-array-vs-array-isarray/33,所以请尽情享受吧。

注意:@escapenescape在jspef.com关闭时创建了另一个测试。http://jsben.ch//qgyav我想确保原始链接在jspef恢复在线时保持不变。


您还可以使用:

1
2
3
4
5
if (value instanceof Array) {
  alert('value is Array!');
} else {
  alert('Not an array');
}

在我看来,这是一个相当优雅的解决方案,但对每个人来说都是自己的。

编辑:

从ES5开始,还有:

1
Array.isArray(value);

但这将在旧浏览器上中断,除非您使用polyfill(基本上…IE8或类似)。


我注意到有人提到jquery,但我不知道有一个isArray()函数。原来它是在1.3版中添加的。

jquery按照peter的建议实现它:

1
2
3
isArray: function( obj ) {
    return toString.call(obj) ==="[object Array]";
},

我已经对jquery有了很大的信心(尤其是它们的跨浏览器兼容性技术),所以我要么升级到1.3版并使用它们的功能(前提是升级不会造成太多问题),要么直接在我的代码中使用这个建议的方法。

非常感谢您的建议。


有多种解决方案都有自己的特点。本页提供了一个很好的概述。一种可能的解决方案是:

1
2
3
function isArray(o) {
  return Object.prototype.toString.call(o) === '[object Array]';
}


在现代浏览器(和一些传统浏览器)中,您可以

1
Array.isArray(obj)

(支持Chrome5、Firefox 4.0、IE 9、Opera10.5和Safari 5)

如果需要支持旧版本的IE,可以使用es5填充程序来polyfill array.isarray;或添加以下内容

1
2
3
4
5
6
# only implement if no native implementation is available
if (typeof Array.isArray === 'undefined') {
  Array.isArray = function(obj) {
    return Object.prototype.toString.call(obj) === '[object Array]';
  }
};

如果使用jquery,可以使用jQuery.isArray(obj)$.isArray(obj)。如果使用下划线,则可以使用_.isArray(obj)

如果不需要检测在不同帧中创建的数组,也可以使用instanceof

1
obj instanceof Array

注:可用于访问函数参数的arguments关键字不是数组,尽管它(通常)的行为类似于数组:

1
2
3
4
5
6
7
8
var func = function() {
  console.log(arguments)        // [1, 2, 3]
  console.log(arguments.length) // 3
  console.log(Array.isArray(arguments)) // false !!!
  console.log(arguments.slice)  // undefined (Array.prototype methods not available)
  console.log([3,4,5].slice)    // function slice() { [native code] }
}
func(1, 2, 3)


这是一个古老的问题,但有了同样的问题,我发现了一个非常优雅的解决方案,我想和大家分享。

向数组中添加原型非常简单

1
Array.prototype.isArray = true;

现在,如果您有一个对象要测试它是否是数组,那么您只需要检查新属性

1
2
3
4
5
var box = doSomething();

if (box.isArray) {
    // do something
}

只有当IsArray的数组


克劳福德:

1
2
3
4
5
6
7
8
9
10
11
12
13
function typeOf(value) {
    var s = typeof value;
    if (s === 'object') {
        if (value) {
            if (value instanceof Array) {
                s = 'array';
            }
        } else {
            s = 'null';
        }
    }
    return s;
}

Crockford提到的主要失败是无法正确确定在不同上下文中创建的数组,例如window。如果这还不够的话,这个页面有一个更复杂的版本。


我个人喜欢彼得的建议:https://stackoverflow.com/a/767499/414784(用于ecmascript 3)。对于ecmascript 5,使用Array.isArray()

然而,对文章的评论表明,如果toString()完全改变,那么检查数组的方法将失败。如果您真的想明确一点,确保toString()没有被更改,并且对象类属性没有问题([object Array]是数组对象的类属性),那么我建议您这样做:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//see if toString returns proper class attributes of objects that are arrays
//returns -1 if it fails test
//returns true if it passes test and it's an array
//returns false if it passes test and it's not an array
function is_array(o)
{
    // make sure an array has a class attribute of [object Array]
    var check_class = Object.prototype.toString.call([]);
    if(check_class === '[object Array]')
    {
        // test passed, now check
        return Object.prototype.toString.call(o) === '[object Array]';
    }
    else
    {
        // may want to change return value to something more desirable
        return -1;
    }
}

注意,在javascript的最终指南第6版7.10中,它说Array.isArray()是使用ecmascript 5中的Object.prototype.toString.call()实现的。还要注意,如果您要担心toString()的实现更改,那么您还应该担心其他内置方法也会更改。为什么使用push()?有人可以改变它!这种做法是愚蠢的。上述支票是为那些担心toString()变更的人提供的解决方案,但我相信支票是不必要的。


当我发布这个问题时,我使用的jquery版本不包括isArray函数。如果有,我可能只是使用它,相信实现是执行这种特定类型检查的最佳浏览器独立方式。

因为jquery现在提供了这个函数,所以我总是使用它…

1
$.isArray(obj);

(从1.6.2版开始)它仍然是通过对表单中的字符串进行比较来实现的

1
toString.call(obj) ==="[object Array]"


如果您只处理ecmascript 5及更高版本,那么可以使用内置的Array.isArray函数

例如。,

1
2
3
Array.isArray([])    // true
Array.isArray("foo") // false
Array.isArray({})    // false

我想我应该为那些可能已经在脚本中使用了underline.js库的人添加另一个选项。.js具有isarray()函数(请参见http://underlinejs.org/isarray)。

1
_.isArray(object)

Returns true if object is an Array.


如果使用angular,则可以使用angular.isarray()函数

1
2
3
4
5
var myArray = [];
angular.isArray(myArray); // returns true

var myObj = {};
angular.isArray(myObj); //returns false

http://docs.angularjs.org/api/ng/function/angular.isarray网站


在Crockford的javascript中,有一个函数用于检查给定参数是否为数组:

1
2
3
4
5
6
7
var is_array = function (value) {
    return value &&
        typeof value === 'object' &&
        typeof value.length === 'number' &&
        typeof value.splice === 'function' &&
        !(value.propertyIsEnumerable('length'));
};

他解释说:

First, we ask if the value is truthy. We do this to reject null and other falsy values. Second, we ask if the typeof value is 'object'. This will be true for objects, arrays, and (weirdly) null. Third, we ask if the value has a length property that is a number. This will always be true for arrays, but usually not for objects. Fourth, we ask if the value contains a splice method. This again will be true for all arrays. Finally, we ask if the length property is enumerable (will length be produced by a for in loop?). That will be false for all arrays. This is the most reliable test for arrayness that I have found. It is unfortunate that it is so complicated.


通用解决方案如下:

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

从ECMAScript 5开始,正式的解决方案是:

1
Array.isArray(arr)

此外,对于旧的javascript libs,您可以找到以下解决方案,尽管它不够精确:

1
2
3
4
5
6
7
var is_array = function (value) {
    return value &&
    typeof value === 'object' &&
    typeof value.length === 'number' &&
    typeof value.splice === 'function' &&
    !(value.propertyIsEnumerable('length'));
};

这些解决方案来自http://www.pixelstech.net/topic/85-how-to-check-an-object-is-an-array-or-not-in-javascript


我用的是这行代码:

1
2
3
if (variable.push) {
   // variable is array, since AMAIK only arrays have push() method.
}


代码引用自https://github.com/miksago/evan.js/blob/master/src/evan.js

1
2
  var isArray = Array.isArray || function(obj) {
    return !!(obj && obj.concat && obj.unshift && !obj.callee);};


对于那些编码高尔夫的人来说,一个不可靠的测试用最少的字符:

1
2
3
function isArray(a) {
  return a.map;
}

这通常在遍历/展平层次时使用:

1
2
3
4
5
6
function golf(a) {
  return a.map?[].concat.apply([],a.map(golf)):a;
}

input: [1,2,[3,4,[5],6],[7,[8,[9]]]]
output: [1, 2, 3, 4, 5, 6, 7, 8, 9]

来自W3Chans:

1
2
3
function isArray(myArray) {
    return myArray.constructor.toString().indexOf("Array") > -1;
}

我已经创建了这个小代码,它可以返回真正的类型。

我还不确定性能,但这是一种正确识别类型的尝试。

https://github.com/valtido/better-typeof也在这里写了一些关于它的博客http://www.jqui.net/jquery/better-typeof-than-the-javascript-native-typeof/

它工作,类似于当前的类型。

1
2
var user = [1,2,3]
typeOf(user); //[object Array]

它认为它可能需要一些微调,并考虑到一些事情,我没有遇到或测试它适当。因此,我们欢迎进一步的改进,无论是性能方面的改进,还是错误地重新移植类型。


我认为使用myobj.constructor==object和myarray.constructor==array是最好的方法。它比使用ToString()快20倍。如果您使用自己的构造函数扩展对象,并且希望这些创建被视为"对象",那么这样做不起作用,但在其他方面会更快。typeof和constructor方法一样快,但typeof[]='object'返回true,这通常是不需要的。http://jspef.com/constructor-vs-tostring

需要注意的一点是,null.constructor将抛出一个错误,因此如果您可能要检查空值,则必须首先执行if(testthing!{=空){}


我喜欢布莱恩的回答:

1
2
3
4
5
6
7
8
9
10
11
function is_array(o){
    // make sure an array has a class attribute of [object Array]
    var check_class = Object.prototype.toString.call([]);
    if(check_class === '[object Array]')    {
        // test passed, now check
        return Object.prototype.toString.call(o) === '[object Array]';
    } else{
        // may want to change return value to something more desirable
        return -1;
    }
}

但你可以这样做:

1
return Object.prototype.toString.call(o) === Object.prototype.toString.call([]);

因为.length属性对于javascript中的数组是特殊的,所以您可以简单地说

1
obj.length === +obj.length // true if obj is an array

下划线和其他几个库使用这个简单而简短的技巧。


我刚刚想到的:

if (item.length)
//This is an array
else
//not an array