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

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

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

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

这是最好的方法吗?

答案

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

variable.constructor === Array

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

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

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

其他一些方法是:

Array.isArray(variable)

更新 2019 年 5 月 23 日使用 Chrome 75,喊出 @AnduAndrici 邀请我与他的问题,这最后一个是重温这一点 ,在我看来最丑的,这是最慢的最快的国家之一。 作为第一个示例,运行速度约为 1/5。这个家伙慢了大约 2%到 5%,但这很难说。牢固使用!结果给人留下了深刻的印象。 Array.prototype 实际上是一个数组。您可以在这里阅读有关它的更多信息https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray

variable instanceof Array

作为第一个示例,此方法的运行速度约为1/3 。如果您只关注漂亮的代码,而不是关注太多性能,那么它仍然很坚固,看上去更干净。请注意,检查数字不能作为variable instanceof Number始终返回false更新: instanceof现在的速度提高了 2/3!

所以还有另一个更新

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

这个家伙是最慢的尝试检查数组的人。但是,这是您要寻找的任何类型的一站式商店。但是,由于您要查找数组,因此请使用上面最快的方法。

另外,我进行了一些测试: http : //jsperf.com/instanceof-array-vs-array-isarray/35因此,请找点乐子并检查一下。

注意:由于 jsperf.com 关闭,@ EscapeNetscape 创建了另一个测试。 http://jsben.ch/#/QgYAV我想确保当 jsperf 再次联机时,原始链接保持不变。

您还可以使用:

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

在我看来,这是一个非常优雅的解决方案,但对每个人来说都是如此。

编辑:

从 ES5 开始,现在还有:

Array.isArray(value);

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

有多种解决方案,各有其独特之处。 该页面提供了很好的概述。一种可能的解决方案是:

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

我注意到有人提到 jQuery,但是我不知道有一个isArray()函数。事实证明,它是在 1.3 版中添加的。

jQuery 按照 Peter 的建议实现了它:

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

已经对 jQuery 充满信心(尤其是他们的跨浏览器兼容性技术),我将升级到 1.3 版并使用其功能(假设升级不会引起太多问题),或者直接在我的文档中使用此建议的方法码。

非常感谢您的建议。

在现代浏览器(和某些旧版浏览器)中,您可以

Array.isArray(obj)

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

如果需要支持 IE 的较早版本,则可以使用es5-shim填充 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)

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

向 Array 添加原型可以使其非常简单

Array.prototype.isArray = true;

现在,如果您有一个对象,则要测试以查看其是否为数组,只需检查新属性即可

var box = doSomething();

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

isArray 仅在其数组时可用

通过克罗克福德

function typeOf(value) {
    var s = typeof value;
    if (s === 'object') {
        if (value) {
            if (value instanceof Array) {
                s = 'array';
            }
        } else {
            s = 'null';
        }
    }
    return s;
}

克罗克福德最主要的失败之处是无法正确确定在其他上下文(例如window中创建的数组。如果这还不够的话,该页面的版本要复杂得多。

我个人喜欢彼得的建议: https : Array.isArray()对于 ECMAScript3。对于 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 权威指南第 6 版,7.10,它说Array.isArray()使用实施Object.prototype.toString.call() ECMAScript 中 5. 另请注意,如果你要担心toString() ' 在更改实现时,您还应该担心其他所有内置方法也都需要更改。为什么要使用push() ?有人可以更改它!这种方法很愚蠢。上面的检查是为那些担心toString()更改的人提供的解决方案,但我认为该检查是不必要的。

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

例如,

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

当我发布此问题时,我正在使用的 JQuery 版本没有包含isArray函数。如果有的话,我可能会相信它是实现此特定类型检查的独立于浏览器的最佳方式。

由于 JQuery 现在确实提供了此功能,因此我将始终使用它...

$.isArray(obj);

(从 1.6.2 版开始)仍然可以通过以下形式对字符串进行比较来实现

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