题 检查对象是否是数组?


我正在尝试编写一个接受字符串列表或单个字符串的函数。如果它是一个字符串,那么我想将它转换为只有一个项目的数组。然后我可以循环它而不用担心错误。

那么我该如何检查变量是否是一个数组?


我已经收集了下面的各种解决方案并创建了一个 jsperf测试


2146
2018-01-23 18:53


起源


我认为你的意思是“检查对象是否是一个数组”,但你想要检查'对象是一个字符串数组还是一个字符串'。不确定你是否看到了它?还是只是我?我想的更像是 这个我在这里错过了什么吗? - rr1g0
TL; DR  - arr.constructor === Array 是最快的。 - Neta
jsben.ch/#/QgYAV  - 最常见方式的基准 - EscapeNetscape
TL; DR  - 数组。IsArray的(ARR) 自ES5以来;和$。IsArray的(ARR) 在jQuery中。 - Ondra Žižka
请记住,如果您因任何原因通过原型覆盖您的构造函数 arr.constructor === Array test将返回false。 Array.isArray(arr) 仍然返回true。 - ghaschel


答案:


在现代浏览器中,您可以做到

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

319
2018-01-06 18:11



这里有一个 更完整 支持的浏览器列表 Array.isArray - lightswitch05
if (typeof Array.isArray === 'undefined') { 可以改为 if(!Array.isArray) { - iMatoria
物有所值 Object.prototype.string.call(obj)如果对象有,可以欺骗 Symbol.toStringTag 在上面。这就是说我不知道​​任何出货的环境 Symbol.toStringTag 但不是 Array.isArray 所以这似乎很安全。 - Benjamin Gruenbaum


ECMAScript标准中给出的用于查找Object类的方法是使用 toString 方法来自 Object.prototype

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

或者你可以使用 typeof 测试它是否是一个字符串:

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

或者,如果你不关心性能,你可以做一个 concat 到一个新的空数组。

someVar = [].concat( someVar );

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

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

看看一个 彻底治疗 从 @ T.J。克劳德的 博客,如下面的评论中所述。

看看这个 基准 了解哪种方法表现更好: 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']

1866
2018-01-23 18:54



+1 Yup, toString 是一种方法。我在这里做了一些综述: blog.niftysnippets.org/2010/09/say-what.html - T.J. Crowder
如果你不想输入“[object Array]”,请使用Object.prototype.toString.call(someVar)=== Object.prototype.toString.call([])或者设置一个方便的函数来获取类型我想输入Object.prototype.toString.call - Pramod
哇。 concat方法是一只患病的大鼠。我会给+2,但这是不允许的 - Dark Star1
我使用vanilla Array.isArray,它在'现代浏览器'中工作(即IE9 +和其他所有人)。对于旧浏览器支持,请使用MDN中的填充程序 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... - David Gilbertson
生活在现代世界 - Array.isArray(obj) - mcfedr


我先检查一下你的实现是否支持 isArray

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

你也可以尝试使用 instanceof 操作者

v instanceof Array

1225
2018-01-23 18:55



+1 for instanceof Array。最简单的AFAICT - Tom Auger
v instanceof Array 如果,将返回false v 是在另一个框架中创建的(v 是的例子 thatFrame.contentWindow.Array 类)。 - pepkin88
再具体一点: Array.isArray 被定义为ECMAScript 5 / Javascript 1.8.5的一部分。 - jevon
非常简单和整洁的解决方案BUT isArray与一些旧的浏览器(e.x. IE7和IE8)不兼容。资源: kangax.github.io/es5-compat-table/# - Wookie88
怎么样:if(Array.isArray)返回Array.isArray(v); else return v instanceof Array; - lewdev


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>


283
2018-04-02 12:15



作为参考: api.jquery.com/jQuery.isArray - Akseli Palén
只需注意,jQuery在内部使用toString方法: GitHub来源 - Jacob Squires
@JacobSquires取决于。我刚刚在这里测试了Chrome上最新的jQuery - $.isArray === Array.isArray 正在回归真实。 - Renan
@Renan:这是使用jQuery的好处。它通常使用最现代和最好的方法来完成它,并且您不必自己进行所有功能检查以了解要使用的内容。 - awe
但没有人会使用jQuery JUST FOR这个功能,对吧?我不会只下载jquery因为我想检查是否有数组:p - Automagisch


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

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

84
2017-12-06 10:12



你是对的,根据我在问题中包含的测试,这是最快的。 - mpen
使用这种方法有什么缺点吗?它似乎比公认的最佳答案更简单有效。 - David Meza
@shinobi - 只是好奇(我经常看到这个) - 你为什么要说出这个条件 if (obj && Array === obj.constructor) 而不是 if (obj && obj.constructor === Array) ?它是翻译成英语,然后编码的东西吗?例如,英语使用者通常会问“对象是否存在,并且它的构造函数是否来自数组类?”,因此读取它时的代码流更合乎逻辑。还是有一些技术原因? - unsynchronized
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();} - unsynchronized
@shinobi都很好。我想它可能是一个安全的习惯的宿醉 - 如果你不小心使用=而不是==,它不会编译为不是可分配的变量。 - unsynchronized


Array.isArray运行速度很快,但并不是所有版本的浏览器都支持它。 所以你可以为其他人做一个例外并使用通用方法:

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

31
2017-12-10 17:01



您可能希望添加代码说明,以便更容易理解其他用户,但除此之外 - 很好。 +1 - Jeff
你需要得到 .toString() 方法来自 Object.prototype。现在你正在使用 window.toString(),这是不一样的。 - the system
你是对的。 window.toString 做同样的事 Object.prototype.toString 只是在Chrome中。 - CruorVult
哇(数组中的'isArray')。从来没有见过它。 THKS - Ivan Ferrer Villa
isArray根本不快。这是最慢的方法。 - jemiloii


想象一下,下面有这个数组:

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);

29
2017-12-27 13:17