如何检查对象是否为数组?


2748

我正在尝试编写一个接受字符串列表或单个字符串的函数。如果它是一个字符串,那么我想将其转换为仅包含一项的数组,因此我可以遍历它而不必担心错误。

那么,如何检查变量是否为数组?


我整理了以下各种解决方案,并创建了jsperf测试。它们都非常快,因此只需使用Array.isArray- 现在得到很好的支持,并且可以跨框架使用


6
我以为您的意思是“检查对象是否为数组”,但您想具体检查“对象是否为字符串数组或单个字符串”。不确定是否看到了?还是只是我?我想的更多的东西像这样 ......我在一个失去了一些东西?
rr1g0

149
TL; DR - arr.constructor === Array是最快的。
塔2015年

3
jsben.ch/#/QgYAV-最常见方式的基准
-EscapeNetscape

39
TL; DR-阵列。自ES5起isArray(arr) ; 和$。jQuery中的isArray(arr)
OndraŽižka'16

6
请记住,如果您出于任何原因通过原型覆盖了构造函数,则arr.constructor === Array测试将返回false。Array.isArray(arr)仍然返回true。
ghaschel

Answers:


974

在现代浏览器中,您可以

Array.isArray(obj)

Chrome 5,Firefox 4.0,IE 9,Opera 10.5和Safari 5支持)

为了向后兼容,您可以添加以下内容

# 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

obj instanceof Array

9
下面是一个更完整的浏览器的列表支持Array.isArray
lightswitch05

if (typeof Array.isArray === 'undefined') {可以更改为if(!Array.isArray) {
iMatoria

Object.prototype.string.call(obj)如果物体上面有东西,那它的价值就可以被欺骗Symbol.toStringTag。就是说,我不知道会带来什么环境,Symbol.toStringTag但是Array.isArray似乎没有安全感。
本杰明·格伦鲍姆

5
instanceof Array如果数组来自其他框架,为什么会失败?
NobleUplift

16
@NobleUplift:instanceof Array如果数组来自不同的框架则失败,因为来自该不同框架的每个数组都有不同的Array构造函数和原型。出于兼容性/安全性原因,每个框架都有其自己的全局环境,其中包括全局对象。在Object从一帧全球是从不同Object的另一个世界。对于全球人士也是如此ArrayAxel Rauschmayer对此进行了更多讨论
jschoi

1943

ECMAScript标准中提供的用于找到Object类的toString方法是使用中的方法Object.prototype

if( Object.prototype.toString.call( someVar ) === '[object Array]' ) {
    alert( 'Array!' );
}

或者您可以使用typeof它来测试它是否为字符串:

if( typeof someVar === 'string' ) {
    someVar = [ someVar ];
}

或者,如果您不关心性能,则可以concat对一个新的空数组执行a操作。

someVar = [].concat( someVar );

还有一个可以直接查询的构造函数:

if (somevar.constructor.name == "Array") {
    // do something
}

检查出一个彻底的治疗@TJ克罗德的博客,张贴在下面他的评论。

查看此基准,以了解哪种方法效果更好:http : //jsben.ch/#/QgYAV

@Bharath使用Es6将字符串转换为数组以解决以下问题:

const convertStringToArray = (object) => {
   return (typeof object === 'string') ? Array(object) : object 
}

假设:

let m = 'bla'
let n = ['bla','Meow']
let y = convertStringToArray(m)
let z = convertStringToArray(n)
console.log('check y: '+JSON.stringify(y)) . // check y: ['bla']
console.log('check y: '+JSON.stringify(z)) . // check y: ['bla','Meow']

65
+1 toString是,是其中一种方式。我在这里做了一些综述
TJ Crowder

3
typeof new String('beans') >“对象”
2012年

16
如果您不想键入“ [object Array]”,请使用Object.prototype.toString.call(someVar)=== Object.prototype.toString.call([])或使用便捷函数来获取类型不想键入Object.prototype.toString.call
Pramod

13
我使用在“现代浏览器”(即IE9 +和其他所有版本)中运行的vanilla Array.isArray。而对于旧的浏览器支持使用来自MDN垫片developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
大卫·吉尔伯特

21
生活在现代世界中–Array.isArray(obj)
mcfedr

1273

我将首先检查您的实现是否支持isArray

if (Array.isArray)
    return Array.isArray(v);

您也可以尝试使用instanceof运算符

v instanceof Array

127
v instanceof Array如果v是在另一个框架(vthatFrame.contentWindow.Array类的实例)中创建的,则将返回false 。
pepkin88 2012年

47
具体而言:Array.isArray定义为ECMAScript 5 / Javascript 1.8.5的一部分。
jevon 2012年

8
真正简单整洁的解决方案BUT isArray与某些旧版浏览器(例如IE7和IE8)不兼容。来源:kangax.github.io/es5-compat-table/#
Wookie88

2
怎么样:如果(Array.isArray)返回Array.isArray(v); 否则返回v instanceof Array;
lewdev 2015年

1
或者只是:return (Array.isArray && Array.isArray(v)) || (v instanceof Array);
Stijn de Witt 2015年

298

jQuery还提供了一种$.isArray()方法:

var a = ["A", "AA", "AAA"];

if($.isArray(a)) {
  alert("a is an array!");
} else {
  alert("a is not an array!");
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


27
请注意,jQuery在内部使用toString方法:GitHub Source
Jacob Squires 2014年

5
@JacobSquires取决于。我刚刚在这里进行了测试,Chrome上的最新jQuery- $.isArray === Array.isArray返回true。
雷南2014年

3
@Renan:这是使用jQuery的好处。它通常使用最现代,最好的方法来执行此操作,而不必检查所有功能以了解使用什么。
2015年

jQuery Array.isArray在幕后使用:github.com/jquery/jquery/blob/master/src/core.js#L211
Sergiu

1
但是没有人会使用jQuery JUST FOR此功能,对吗?我不只是下载jquery,因为我想检查某物是否为数组:p
Automagisch

105

在所有方法(支持所有浏览器)中,这是最快的:

function isArray(obj){
    return !!obj && obj.constructor === Array;
}

2
没错,根据我在问题中包含的测试,这是最快的。
mpen 2015年

5
使用此方法有什么缺点吗?它似乎比公认的最佳答案更简单,更有效。
David Meza

@shinobi-很好奇(而且我经常看到这种情况)-为什么要说条件if (obj && Array === obj.constructor)而不是if (obj && obj.constructor === Array)?翻译成英文,然后编码成东西是不是迷失了?例如,说英语的人通常会问“对象是否存在,并且它的构造函数是否来自数组类?”,因此读取对象时的代码流更加合乎逻辑。还是有一些技术原因?
不同步的

function object_type(o){var t = typeof(o);return ((t==="object") && (o.constructor===Array)) ? "array" : t;} /*allows you to */ switch(object_type(o)){ case 'array': break; case 'object' : o.dosomething();}
不同步的

3
@shinobi都很好。我想这可能是一个安全的c习惯的宿醉-如果您不小心使用=而不是==,它将不会编译,因为它不是可分配的变量。
不同步的

47

假设您在下面有这个数组

var arr = [1,2,3,4,5];

Javascript(新旧浏览器):

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

要么

function isArray(arr) {
  return arr instanceof Array;
}

要么

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

然后这样称呼它:

isArray(arr);

Javascript(IE9 +,Ch5 +,FF4 +,Saf5 +,Opera10.5 +)

Array.isArray(arr);

jQuery的:

$.isArray(arr);

角度:

angular.isArray(arr);

下划线和Lodash:

_.isArray(arr);

34

Array.isArray可以快速运行,但并非所有版本的浏览器都支持。因此,您可以为其他人设置例外并使用通用方法:

    Utils = {};    
    Utils.isArray = ('isArray' in Array) ? 
        Array.isArray : 
        function (value) {
            return Object.prototype.toString.call(value) === '[object Array]';
        }

3
您需要从获取.toString()方法Object.prototype。现在您正在使用window.toString(),这是不一样的。
系统

你是对的。window.toStringObject.prototype.toString在Chrome中一样。
CruorVult13年

isArray根本不是很快。这是最慢的方法。
jemiloii

为什么不将其添加到Array而不是Utils?(我知道您不希望新数组对象具有额外的属性,但我认为只有在将isArray添加到Array.prototype时才会发生。)
David Winiecki 2014年

27

简单的功能检查一下:

function isArray(object)
{
    return object.constructor === Array;
}

16
我会将其减少到一行return object.constructor === Array-但您确定这只会对数组返回true吗?
mpen 2012年

12
可以使用所有布尔表达式来做到这一点。当我看到if(x) return true; else return false:-) 时让我发疯:-)即使它倒退,您也应该取反表达式。
mpen 2012年

3
对于getElementsByTagName,此方法未返回true的原因是,该函数的结果实际上是HTMLCollection而不是数组。
Yuval A. 2014年

6
如果object是undefined或null,则此操作将严重失败。
John Henckel 2015年

1
@JohnHenckel参见我的答案stackoverflow.com/a/29400289/34806,它同时考虑了您的关注和第一条评论
-Dexygen

17

正如MDN 在这里所说:

使用Array.isArrayObject.prototype.toString.call区分常规对象和数组

像这样:

  • Object.prototype.toString.call(arr) === '[object Array]', 要么

  • Array.isArray(arr)


17

这个问题只有一种解决方案

x instanceof Array

其中x是变量,如果x是一个数组,它将返回true,否则返回false。


更清洁,未来更安全!这还是一个typeof比较。
ChristoKiwi '17

这是否获得了很多浏览器支持?我喜欢。
Dan Zuzevich '17

1
不幸的是,如果没有try / catch,这实际上是没有用的,因为如果“ x”是一个对象(例如{}数组),则会出现语法错误。
abalter

15

您可以检查变量的类型是否为数组;

var myArray=[];

if(myArray instanceof Array)
{
....
}

1
一些人已经提到instanceof..我认为它在一些奇怪的情况下会失败。
mpen

15

我将提供一个功能来测试您要处理的对象的类型...

function whatAmI(me){ return Object.prototype.toString.call(me).split(/\W/)[2]; }

// tests
console.log(
  whatAmI(["aiming","@"]),
  whatAmI({living:4,breathing:4}),
  whatAmI(function(ing){ return ing+" to the global window" }),
  whatAmI("going to do with you?")
);

// output: Array Object Function String

那么您可以编写一个简单的if语句...

if(whatAmI(myVar) === "Array"){
    // do array stuff
} else { // could also check `if(whatAmI(myVar) === "String")` here to be sure
    // do string stuff
}

12

我用一种非常简单的方式来做。为我工作。有什么缺点吗?

Array.prototype.isArray = true;

a=[]; b={};
a.isArray  // true
b.isArray  // (undefined -> false)

7
{isArray:true}
Bergi

JSON.parse(someDataFromElsewhere).items.isArray可能会返回true(取决于数据)并破坏您的代码。
罗伊·廷克

12

考虑到以下评论,这是我尝试改善此答案的尝试:

var isArray = myArray && myArray.constructor === Array;

它摆脱了if / else,并考虑了数组为null或undefined的可能性


ES5中没有构造函数
TechTurtle


11

我用两种替代方法以及错误检查更新了jsperf提琴

事实证明,在“对象”和“数组”原型中定义常量值的方法比任何其他方法都快。这是一个令人惊讶的结果。

/* Initialisation */
Object.prototype.isArray = function() {
  return false;
};
Array.prototype.isArray = function() {
  return true;
};
Object.prototype._isArray = false;
Array.prototype._isArray = true;

var arr = ["1", "2"];
var noarr = "1";

/* Method 1 (function) */
if (arr.isArray()) document.write("arr is an array according to function<br/>");
if (!noarr.isArray()) document.write("noarr is not an array according to function<br/>");
/* Method 2 (value) - **** FASTEST ***** */
if (arr._isArray) document.write("arr is an array according to member value<br/>");
if (!noarr._isArray) document.write("noarr is not an array according to member value<br/>");

如果变量采用未定义的值,这两种方法将不起作用,但是,如果您确定它们具有值,则它们将起作用。关于考虑性能的问题,值是数组还是单个值,第二种方法看起来像是有效的快速方法。它比Chrome上的“ instanceof”稍快,是Internet Explorer,Opera和Safari(在我的机器上)的次佳方法的两倍。


9

我知道,人们正在寻找某种原始的javascript方法。但是,如果您想考虑的较少,请看这里:http : //underscorejs.org/#isArray

_.isArray(object) 

如果object是Array,则返回true。

(function(){ return _.isArray(arguments); })();
=> false
_.isArray([1,2,3]);
=> true

7
“除非还包括用于框架/库的另一个标签,否则期望纯JavaScript答案。”
米哈尔Perłakowski

5

我见过的最好的解决方案是跨浏览器替换typeof。在此处检查Angus Croll的解决方案。

TL; DR版本在下面,但是本文对这个问题进行了很好的讨论,因此如果有时间,您应该阅读它。

Object.toType = function(obj) {
    return ({}).toString.call(obj).match(/\s([a-z|A-Z]+)/)[1].toLowerCase();
}
// ... and usage:
Object.toType([1,2,3]); //"array" (all browsers)

// or to test...
var shouldBeAnArray = [1,2,3];
if(Object.toType(shouldBeAnArray) === 'array'){/* do stuff */};

5

这是我的懒惰方法:

if (Array.prototype.array_ === undefined) {
  Array.prototype.array_ = true;
}

// ...

var test = [],
    wat = {};

console.log(test.array_ === true); // true
console.log(wat.array_ === true);  // false

我知道要“与”原型“讨好”是牺牲品,但它的性能似乎明显优于推荐的toString方法

注:此方法的缺陷是,它不会工作跨越iframe边界,但我的使用情况下,这不是一个问题。


它的性能不再更好,至少在Ubuntu 64位上的FF30上有效
test30 2014年

2
wat = {array_: true}物体欺骗。
Bergi

@Bergi:是的,这很明显。如果你正在设置obj.array_ = true,那么你只是在自欺欺人
namuol

@namuol:我不一定要自欺欺人。通常,足够多的对象用作字典。考虑一个cache对象来记住搜索结果,该结果使用搜索字符串作为属性键。如果用户搜索该array_怎么办?您的对象是否因此而成为数组?这只是一个错误。
Bergi 2015年

@namuol:而且,此方法将要求所有相关方(包括使用的库)都同意将.array_其用于标记数组。事实并非如此,这.array可能意味着任何事情。您至少应使用描述性字符串,并指出任意使用的不当性,例如,使用.__isArray = true
Bergi

5

Stoyan Stefanov的书《JavaScript模式》中有一个很好的示例,该示例假定可以处理所有可能的问题并利用ECMAScript 5方法Array.isArray()

所以这里是:

if (typeof Array.isArray === "undefined") {
    Array.isArray = function (arg) {
        return Object.prototype.toString.call(arg) === "[object Array]";
    };
}

顺便说一句,如果您使用的是jQuery,则可以使用它的方法$ .isArray()


2
+1:为什么不简单if(!Array.isArray) {...
Marco Demaio 2014年

5

检查对象是否为数组的最简单,最快的方法。

 var arr = [];
  arr.constructor.name ==='Array'  //return true;

要么

arr.constructor ===Array //return true;

或者您可以使一个实用程序功能:

function isArray(obj){ return obj && obj.constructor ===Array}

用法:

isArray(arr); //return true

5

如果您知道您的对象没有concat方法,则可以使用以下内容。

var arr = [];
if (typeof arr.concat === 'function') {
    console.log("It's an array");
}


这是一个很好的技巧,但是可以重写...但是大多数时候应该可以得到结果
Alireza

5

您可以使用isArray方法,但我希望与

Object.getPrototypeOf(yourvariable) === Array.prototype


你为什么要这样?
mpen

@mpen Object.getPrototypeOf(yourvariable)返回Array对象的原型。并且该代码是最快,最安全的依赖。

1
很容易挫败:pastebin.com/MP8d5bCE另外,您是否进行了性能测试来支持“最快”的要求?
mpen

4

如果只能传递给此函数的两种值是字符串或字符串数​​组,请使其简单并使用typeof检查字符串可能性的方法:

function someFunc(arg) {
    var arr = (typeof arg == "string") ? [arg] : arg;
}

是的...适用于这种情况,但通常不会。最终还是使用了varargs。:)
mpen 2011年

4
A = [1,2,3]
console.log(A.map==[].map)

在搜索最短版本时,这是我到目前为止所得到的。

注意,没有完美的功能可以始终检测所有可能的组合。最好了解工具的所有功能和局限性,而不是期望使用魔术工具。


1
我的轻微衍生,A.map !== undefined但是,是的,在猴子修补程序的世界中可能是一条湿滑的路;)
dmi3y 2013年

仅供参考:这不适用于iFrame(stackoverflow.com/questions/460256/…
WiredPrairie 2013年

4
function isArray(value) {
    if (value) {
        if (typeof value === 'object') {
            return (Object.prototype.toString.call(value) == '[object Array]')
        }
    }
    return false;
}

var ar = ["ff","tt"]
alert(isArray(ar))


4

您可以尝试以下方法:

var arr = []; (or) arr = new Array();
var obj = {}; (or) arr = new Object();

arr.constructor.prototype.hasOwnProperty('push') //true

obj.constructor.prototype.hasOwnProperty('push') // false

4

这个函数将把几乎所有东西变成一个数组:

function arr(x) {
    if(x === null || x === undefined) {
        return [];
    }
    if(Array.isArray(x)) {
        return x;
    }
    if(isString(x) || isNumber(x)) {
        return [x];
    }
    if(x[Symbol.iterator] !== undefined || x.length !== undefined) {
        return Array.from(x);
    }
    return [x];
}

function isString(x) {
    return Object.prototype.toString.call(x) === "[object String]"
}

function isNumber(x) {
    return Object.prototype.toString.call(x) === "[object Number]"
}

它使用了一些较新的浏览器功能,因此您可能想对此进行填充以提供最大支持。

例子:

> arr(null);
[]
> arr(undefined)
[]
> arr(3.14)
[ 3.14 ]
> arr(1/0)
[ Infinity ]
> gen = function*() { yield 1; yield 2; yield 3; }
[Function: gen]
> arr(gen())
[ 1, 2, 3 ]
> arr([4,5,6])
[ 4, 5, 6 ]
> arr("foo")
[ 'foo' ]

NB字符串将被转换为具有单个元素的数组,而不是字符数组。isString如果您不希望这样做,请删除该支票。

我在Array.isArray这里使用过,因为它是最可靠且最简单的。


4

在您的情况下,您可以使用Arrayconcat方法,该方法既可以接受单个对象,也可以接受数组(甚至可以合并):

function myFunc(stringOrArray)
{
  var arr = [].concat(stringOrArray);

  console.log(arr);

  arr.forEach(function(item, i)
  {
    console.log(i, "=", item);
  })
}

myFunc("one string");

myFunc(["one string", "second", "third"]);

concat 似乎是Array最古老的方法之一(即使IE 5.5也很清楚)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.