检查对象是否类似于数组

Kev*_*ans 10 javascript arrays

有没有办法检查对象是否是"类似于数组",就像这些类型的对象一样:

  • 数组(duh)
  • 类型化数组(Uint8Array等),这些将在Array.isArray使用时返回false
  • 参数对象
  • *的NodeLists
  • 还有一些我无法想到的其他问题

我想你可以检查是否存在.length属性,但非类数组对象可以包含该.length属性.我猜这些共同的东西是数组访问器.

jfr*_*d00 9

正如我在研究这个主题时发现的那样,你只有几个选择:

  1. 您只能查看.length属性并接受任何似乎具有适当.length属性的对象,这些属性不是您应该消除的任何其他内容(如函数).

  2. 您可以检查特定的类似数组的对象(HTMLCollection,nodeList)和偏向它们的偏见.

以下是第一种方法的两个选项 - 一个不接受零长度,另一个接受(这些包含了gilly3的建议以及我们在jQuery的类似函数中看到的内容):

// see if it looks and smells like an iterable object, but don't accept length === 0
function isArrayLike(item) {
    return (
        Array.isArray(item) || 
        (!!item &&
          typeof item === "object" &&
          item.hasOwnProperty("length") && 
          typeof item.length === "number" && 
          item.length > 0 && 
          (item.length - 1) in item
        )
    );
}
Run Code Online (Sandbox Code Playgroud)

当然,这会报告false项目.length === 0,如果您想允许.length === 0,那么逻辑也可以包括该情况.

// see if it looks and smells like an iterable object, and do accept length === 0
function isArrayLike(item) {
    return (
        Array.isArray(item) || 
        (!!item &&
          typeof item === "object" &&
          typeof (item.length) === "number" && 
          (item.length === 0 ||
             (item.length > 0 && 
             (item.length - 1) in item)
          )
        )
    );
}
Run Code Online (Sandbox Code Playgroud)

一些测试用例:http://jsfiddle.net/jfriend00/3brjc/

2)在检查它是否不是实际数组之后,您可以编码以检查特定类型的类数组对象(例如nodeList,HTMLCollection).

例如,这是我想要确保包含nodeList和HTMLCollection类数组对象时使用的方法:

// assumes Array.isArray or a polyfill is available
function canAccessAsArray(item) {
    if (Array.isArray(item)) {
        return true;
    }
    // modern browser such as IE9 / firefox / chrome etc.
    var result = Object.prototype.toString.call(item);
    if (result === "[object HTMLCollection]" || result === "[object NodeList]") {
        return true;
    }
    //ie 6/7/8
    if (typeof item !== "object" || !item.hasOwnProperty("length") || item.length < 0) {
        return false;
    }
    // a false positive on an empty pseudo-array is OK because there won't be anything
    // to iterate so we allow anything with .length === 0 to pass the test
    if (item.length === 0) {
        return true;
    } else if (item[0] && item[0].nodeType) {
        return true;
    }
    return false;        
}
Run Code Online (Sandbox Code Playgroud)