检查对象是否类似于数组

时间:2014-06-04 22:18:08

标签: javascript arrays

有没有办法检查某个对象是否类似于#34;就像这些类型的对象一样:

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

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

6 个答案:

答案 0 :(得分:9)

我在这个主题的研究中发现,你只有几个选择:

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

  2. 您可以检查特定的类似数组的对象(HTMLCollectionnodeList)并偏向它们。

  3. 这是第一种方法的两个选项 - 一个不接受零长度的方法和一个方法(这些包含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
            )
        );
    }
    

    当然,这会为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)
              )
            )
        );
    }
    

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

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

    例如,这是我想要确保包含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;        
    }
    

答案 1 :(得分:0)

嗯,这取决于你的意思是数组式的。可能你可以用这样的for循环迭代:

for (var i=0, l=obj.length; i<l; ++i) {
  var item = obj[i];
}

那么测试很简单:

function isArrayLike(obj) {
  if (!obj) return false;
  var l = obj.length;
  if (typeof l != 'number' || l < 0) return false;
  if (Math.floor(l) != l) return false;
  // fast check
  if (l>0 && !((l-1) in obj)) return false;
  // more complete check (optional)
  for (var i=0; i<l; ++i) {
    if (!(i in obj)) return false;
  }
  return true;
}

当然,这不会捕获人口稀少的数组,但话说再次,他们真的被用作数组吗?节点列表等不会被稀疏地填充。

享受!

答案 2 :(得分:0)

有一种方法可以检查对象是否类似于数组,即使其中没​​有元素,也可以使用此函数:

isArrayLike = function (_) {

    _[0] = 0; return [].slice.call(_).length >= Object.values(_).length;
}

这使用了一个我意外发现的小黑客,它允许你确定一个对象是(1)一个数组,(2)数组,还是(3)对象/对象。

唯一的缺点是,对于添加了类似对象属性的数组,它无法正常工作,例如arguments

答案 3 :(得分:0)

您可以检查对象是否为可迭代

function isIterable(o){
 return (o!=null && typeof(o[Symbol.iterator])==='function');
}

请注意, 为字符串返回true 。如果有问题,请排除它们:

function isIterable(o){
 return (o!=null && typeof(o[Symbol.iterator])==='function' && typeof(o)!=='string');
}

然后要么使用迭代器访问元素,要么如果要使用常规的 array [0] 方法,只需添加一个length属性检查。


完整的isArrayLike函数:

function isArrayLike(a){
 return (
  a!=null &&
  typeof(a[Symbol.iterator])==='function' &&
  typeof(a.length)==='number' &&
  typeof(a)!=='string'
 );
}

答案 4 :(得分:0)

从技术上来说 ,(几乎)每个对象都是根据标准({{的类型为undefined的类型,因为类型为"length" 3}}):

  

7.3.17 CreateListFromArrayLike(obj [,elementTypes])

     

抽象操作CreateListFromArrayLike用于创建一个List值,其值由类似数组的对象 obj 的索引属性提供。可选参数 elementTypes 是一个ECMAScript 2015 Language Specification §7.3.17, CreateListFromArrayLike (obj [, elementTypes] ),包含创建的List元素值所允许的ECMAScript语言类型的名称。此抽象操作执行以下步骤:

     
      
  1. List obj )。
  2.   
  3. 如果未传递 elementTypes ,则使 elementTypes 为(未定义,空,布尔,字符串,符号,数字,对象)。
  4.   
  5. 如果ReturnIfAbrupt obj )   不是对象,则引发 TypeError 异常。
  6.   
  7. len TypeToLength obj ,{{1}}))。
  8.   
  9. Get len )。
  10.   
  11. 列表为空ReturnIfAbrupt
  12.   
  13. index 为0。
  14.   
  15. 索引 <<< em> len 时重复      
        
    1. indexName List index )。
    2.   
    3. next 成为ToString obj indexName )。
    4.   
    5. Get下一个)。
    6.   
    7. 如果ReturnIfAbrupt下一个)   不是 elementTypes 的元素,则引发 TypeError 异常。
    8.   
    9. next 添加为 list 的最后一个元素。
    10.   
    11. index 设置为 index +1。
    12.   
  16.   
  17. 返回列表
  18.   

通过Type

生成

答案 5 :(得分:0)

我之所以编写此函数,是因为我需要可以在旧浏览器中正常工作的东西。

prepareStatement