如何最好地判断一个对象是否为数组?

12
据我所知,有三种方法可以确定一个对象是否为数组:
1. 如果实现了isArray函数,则使用该函数。 2. 通过检查对象的构造函数是否为Array。 3. 通过使用instanceof运算符来检查对象是否是Array的实例。
Array.isArray()

通过toString方法

Object.prototype.toString.apply( obj ) === "[object Array]"

通过instanceof操作符

obj instanceof Array

两者之间有什么选择的理由吗?


第二个更易于阅读,其他条件相同,这足以让我说它更好。 - Andrew
我忘记了 Array.isObject,谢谢 @arnaud - NebulaFox
如果数组是在另一个窗口中创建的,那么Object.prototype.toString.apply(obj) === "[object Array]"将返回true。 - kennebec
4个回答

6

如果引擎中实现了标准的Array.isArray(),那么最好的方式可能就是使用它:

isArray = Array.isArray(myObject)

Mozilla开发者网络推荐在未实现Array.isArray方法时使用toString()方法:

Compatibility

Running the following code before any other code will create Array.isArray if it's not natively available. This relies on Object.prototype.toString being unchanged and call resolving to the native Function.prototype.call method.

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

jQuery和underscore.js[来源]都使用toString() === "[object Array]"的方式。


如果Array.isArray为null,你不会得到一个空指针异常吗?这意味着你需要先进行一个空值检查。 - Chris Simpson
实际上,Array.isArray()不是像Array.isArray(theObject)这样调用的实例方法。我错误地写成了Object.isArray,已经修正,谢谢。 - Arnaud Le Blanc
在你的第一个要点中,你是说可以使用 Array.isArray() 来检测“类似数组”的对象吗?“它们是一种快速的方法,用于询问对象是否像数组一样。” - user113716
是的,我刚刚把它移除了,因为isArray是Array的静态方法,所以之前的代码是错误的。 - Arnaud Le Blanc
好的,Array.isArray在规范中被定义为基本上是Object.prototype.toString测试(测试内部[[Class]]属性)的包装器。 - user113716

1

如果你想要判断传递给你的参数是否是一个需要迭代的数组,那么有很多代码只是查找一个 .length 属性,并且如果该属性存在,则将其视为数组或伪数组。

这是因为有很多东西实际上并不是数组(但是具有类似数组的功能),你可能希望你的代码将其视为数组。这些东西的例子包括从许多 DOM 调用返回的 jQuery 对象或 nodeList。以下是一个代码示例:

// accepts:
//    single DOM element
//    array of DOM elements
//    nodeList as returned from various DOM functions like getElementsByClassName
//    any array like object with a .length attribute and items in numeric indexes from 0 to .length-1 like a jQuery object
function hideElements(input) {
    if (input.length !== undefined) {
        for (var i = 0, len = input.length; i < len; i++) {
            input[i].style.display = "none";
        }
    } else {
        input.style.display = "none";
    }
    return(input);
}

jQuery的.each()函数在决定它应该像数组一样迭代之前,也会测试传递给它的参数的.length(并验证它不是函数)。

如果这不是您要解决的问题,我可以找到两个使用第一种技术的参考:

  1. jQuery的isArray实现使用第一种技术。
  2. MDN(Mozilla开发者网络)建议在这里使用第一种方法。

1

除非已经证明前者具有显著的性能优势并且我的应用程序需要每一点速度,否则我会选择后者。

原因很简单,就是可读性。


1

instanceof 测试给定的构造函数(Array)是否在对象的原型链中,而你的第二种方法仅检查对象的实际类型。换句话说,如果你的对象继承自 Array,则第二个测试将为 true,但第一个测试将为 false。现在,通常不会从 Array 继承(它在 IE 中无效),但是遍历原型链可能会增加一些开销(尤其是如果对象不是数组)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接