题 如何检查变量是否是JavaScript中的数组? [重复]


这个问题在这里已有答案:

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

我找到了一个可能的解决方案......

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

这是最好的方法吗?


1481
2018-04-20 09:02


起源


检查一个对象是一个数组有一些特定的警告......彼得的答案是你唯一应该使用的答案。 - aleemb
@Andy看来我的答案不是最好的。也许你应该选择一个不同的答案接受? - Peter Smit
好点彼得。我没有意识到你的答案是收到这样的评论。我想我在检查数组时已经开始使用JQuery.isArray函数了,有趣的是,这个实现与此处给出的任何其他答案不同。我已将流行的答案标记为正确。 - Andy McCluggage
对不起,这是错的。我看起来更深一些(从版本1.6.2开始)JQuery仍然使用表单中的比较进行类型检查.... toString.call(obj)===“[object Array]” - Andy McCluggage
对于IE8支持,我会这样做 if ('push' in variable.__proto__),检查一些var是否为数组的最快,最好的方法。 - thednp


答案:


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

variable.constructor === Array

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

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

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

其他一些方法是:

variable instanceof Array

这个方法运行 速度的1/3 作为第一个例子。仍然相当稳固,看起来更干净,如果你只是漂亮的代码,而不是性能。请注意,检查数字不起作用 variable instanceof Number 总是回来 false更新: instanceof 现在速度是2/3!

Array.isArray(variable)

在我看来,最后一个是最丑的,它是最慢的之一。运行速度约为第一个例子的1/5。 Array.prototype,实际上是一个数组。你可以在这里读更多关于它的内容 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray

还有另一个更新

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

这个人是尝试检查数组最慢的人。但是,对于您正在寻找的任何类型,这是一站式商店。但是,由于您正在寻找一个数组,只需使用上面最快的方法。

另外,我跑了一些测试: http://jsperf.com/instanceof-array-vs-array-isarray/33 所以有一些乐趣并检查出来。

注意:@EscapeNetscape在jsperf.com关闭时创建了另一个测试。 http://jsben.ch/#/QgYAV 我希望确保只要jsperf重新上线,原始链接就会保留。


1319
2017-10-29 15:07



将另一个答案扩展到另一个 jsperf在这里测试 使用功能测试(.push && .pop),这种方式最快,并且在所有浏览器(甚至旧版本)中都受支持。问题在于,对象可能具有“推送”和“弹出”属性而不是数组。还要注意,当测试是否是从另一个帧创建(或传递)对象的数组时,大多数测试将失败(因为 排列 在给定的窗口不同于 排列 在框架窗口)。如果数组是通过新数组构建的,或者文字为[...],也有一个问题。 - Nikos M.
请注意,如果您不确定是否已定义变量或者它是否为null,请确保首先执行这些检查,因为这些是没有构造函数的公共值/对象。 - Michael Scott Cuthbert
variable.constructor仅用于检查实际数组。在检查随机对象时(在现实世界中就是这种情况,因为这就是使用此函数的原因),使用instanceof会更快。 jsperf.com/check-if-variable-is-array - Dinu Sorin
注意:'variable.constructor === Array'将抛出EXCEPTION,如果变量为null但是'variable instanceof Array'不是! - JerryGoyal
从Chrome 59开始,isArray()似乎要快得多,所以我认为没有理由在所有情况下都不使用isArray()。 - Hedley Smith


你也可以使用:

if (value instanceof Array) {
  alert('value is Array!');
} else {
  alert('Not an array');
}

这对我来说似乎是一个非常优雅的解决方案,但对于他自己而言。

编辑:

从ES5开始,现在还有:

Array.isArray(value);

但是这会在旧版浏览器上中断,除非你使用的是polyfill(基本上...... IE8或类似的)。


982
2018-04-20 09:05



我建议,如果你不使用多个帧,实际上坚持坚持使用这个“instanceof”运算符。这是检查对象类型的正确方法。 - BYK
如果您尝试测试数组或对象,那么失败的一种情况就是 Array instanceof Object == true。 - Pierre
如果您使用jQuery传递带有find('code')或类似内容的元素,您可能需要检查变量 variable instanceof Object 因为它不是数组的实例。 - tuck
@BrettBender如果您仍处于活动状态,是否可以更新您的答案以反映从ES5开始我们有Array.isArray? - AndrewK
@AndrewK看 Fela Winkelmolen的回答,它有Array.isArray方法。至于这个答案,通过编辑将答案变成不同的答案可能不是一个好主意。 - muffin


我注意到有人提到了jQuery,但我不知道有没有 isArray() 功能。事实证明它是在1.3版本中添加的。

彼得建议jQuery实现它:

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

我已经非常相信jQuery(特别是他们的跨浏览器兼容技术)我将升级到1.3版并使用他们的功能(提供升级不会导致太多问题)或直接在我的使用这个建议的方法码。

非常感谢您的建议。


72
2018-04-20 10:10



看到 本文 有关该主题的良好讨论。结论是使用此解决方案。 - Nick G.
这给了我IE10中的错误SCRIPT65535。 - polm23


有多种解决方案都有自己的怪癖。 这一页 给出一个很好的概述。一种可能的解决方案是

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

71
2018-04-20 09:08



如果仔细阅读,则表示在使用多帧文档时需要使用此方法,不建议这样做。这种方法可以很容易地对“toString”函数稍作修改。 - BYK
因此给出了链接,以便Brett可以检查它们并查看在哪种情况下他的功能必须起作用 - Peter Smit
@icCube请告诉我为什么不走的路! - Peter Smit
请参阅下面的答案。我推荐Peter Smit的方式。 - Brian
这个方法是 由Mozilla推荐。 - Hank


在现代浏览器(以及一些传统浏览器)中,您可以这样做

Array.isArray(obj)

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

如果您需要支持旧版本的IE,可以使用 ES5,垫片 到polyfill Array.isArray;或添加以下内容

# 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

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

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)

54
2018-01-08 07:37



这可能是最现代化的方法。我已经在MDN上看到了polyfill,这意味着Mozilla信任它 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... - John
你错过了吗? prototype 那里?似乎它应该是 Object.prototype.toString.call。 - Brock


这是一个老问题,但有同样的问题,我找到了一个非常优雅的解决方案,我想分享。

将原型添加到Array使其非常简单

Array.prototype.isArray = true;

现在,如果你有一个想要测试的对象,看看它是否只需要检查新属性

var box = doSomething();

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

isArray仅在其数组时才可用


49
2017-10-24 21:12



@Vitimtk原型充当实际对象的后备,因此即使相关数组已经存在,这也应该有效。当然,在处理源代码行之前它不起作用。 - Markus Bruckner
假设没有人这样做 Object.prototype.isArray = true;! :( - ErikE
@ErikE让我大声笑。 this.trollcode = true - omninonsense
请注意,在ES5中 Array.isArray 是一种方法(例如, Array.isArray([1,2,3]) === true所以@ErikE不是一个巨魔。我会避免遵循这个答案,因为它会破坏一些现代浏览器中的代码。 - JaredMcAteer
@Ibu,你可以做到 {}.isArray === true 用我的“解决方案”,这是重点...... - ErikE


通过 克罗克福德

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。 如果这个页面不够用,该页面会有更复杂的版本。


45
2018-04-20 09:07





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

但是,对该帖子的评论表明,如果 toString() 完全改变,检查数组的方式将失败。如果你真的想要具体并确保 toString() 尚未更改,对象类属性没有问题([object Array] 是一个对象的类属性是一个数组),那么我建议做这样的事情:

//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 The Definitive Guide 6th edition,7.10中,它说 Array.isArray() 是使用。实现的 Object.prototype.toString.call() 在ECMAScript 5.还要注意,如果你要担心 toString()的实现在变化,你也应该担心每一个内置方法都在变化。为何使用 push()?有人可以改变它!这种做法很愚蠢。上述检查是为那些担心的人提供的解决方案 toString() 改变,但我相信检查是不必要的。


26
2017-12-03 03:17



很好地呼吁ECMAScript 5标准。当然你无法保证浏览器支持它,但这应该是检查新代码的第一种方法。 - styfle
我首先要说的是,这有点过头了。但是,这样的测试会更健壮吗?: return Object.prototype.toString.call(o) === Object.prototype.toString.call([]); - Grant Lindsay


当我发布这个问题时,我使用的JQuery版本没有包含 isArray 功能。如果它有,我可能只是使用它信任该实现是执行此特定类型检查的最佳浏览器独立方式。

既然JQuery现在确实提供了这个功能,我会一直使用它...

$.isArray(obj);

(从版本1.6.2开始)它仍然使用表单中字符串的比较来实现

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

19
2017-08-08 14:42





我想我会为那些可能已经在他们的脚本中使用Underscore.js库的人添加另一个选项。 Underscore.js有一个isArray()函数(参见 http://underscorejs.org/#isArray)。

_.isArray(object) 

如果object是Array,则返回true。


16
2018-03-16 07:50



下划线js实现使用本机 Array.isArray 如果可用,否则它使用 toString 方法。 - Kris
Lodash中也存在相同的功能 - Jundiaius