Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/451.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 检查对象是否与数组相似_Javascript_Arrays - Fatal编程技术网

Javascript 检查对象是否与数组相似

Javascript 检查对象是否与数组相似,javascript,arrays,Javascript,Arrays,是否有方法检查对象是否为“类似数组”的对象,如以下类型的对象: 阵列(duh) 类型化数组(Uint8Array等),当使用Array.isArray时,这些数组将返回false 参数对象 节点主义者* 还有一些我不能马上想到的 我想您可以检查是否存在.length属性,但非数组类对象可以包含.length属性。我想这些都有一个共同点,那就是数组存取器。我在这方面的研究中发现,您只有两个选择: 您只能查看.length属性,并接受任何似乎具有适当.length属性的对象,该属性不是您知道应该

是否有方法检查对象是否为“类似数组”的对象,如以下类型的对象:

  • 阵列(duh)
  • 类型化数组(Uint8Array等),当使用
    Array.isArray
    时,这些数组将返回false
  • 参数对象
  • 节点主义者*
  • 还有一些我不能马上想到的

我想您可以检查是否存在
.length
属性,但非数组类对象可以包含
.length
属性。我想这些都有一个共同点,那就是数组存取器。

我在这方面的研究中发现,您只有两个选择:

  • 您只能查看
    .length
    属性,并接受任何似乎具有适当
    .length
    属性的对象,该属性不是您知道应该消除的任何其他东西(如函数)

  • 您可以检查特定的类似数组的对象(
    HTMLCollection
    nodeList
    ),并偏向它们

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

    当然,对于
    .length==0
    的项目,这会报告
    false
    ,如果您希望允许
    .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)
              )
            )
        );
    }
    
    一些测试用例:

    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;        
    }
    
    Object.prototype.isArrayLike         = function(){ return false; };
    Array.prototype.isArrayLike          = function(){ return true; };
    NodeList.prototype.isArrayLike       = function(){ return true; };
    HTMLCollection.prototype.isArrayLike = function(){ return true; };
    
    //假设Array.isArray或polyfill可用
    功能CAnacessasarray(项目){
    if(阵列isArray(项目)){
    返回true;
    }
    //现代浏览器,如IE9/firefox/chrome等。
    var result=Object.prototype.toString.call(项目);
    如果(结果==“[object HTMLCollection]”| |结果==“[object NodeList]”){
    返回true;
    }
    //ie 6/7/8
    if(typeof item!=“object”| |!item.hasOwnProperty(“length”)| | item.length<0){
    返回false;
    }
    //空伪数组上的假阳性是可以的,因为不会有任何错误
    //进行迭代,以便允许.length==0的任何内容通过测试
    如果(item.length==0){
    返回true;
    }else if(项[0]&项[0]。节点类型){
    返回true;
    }
    返回false;
    }
    
    好吧,这取决于你所说的“类数组”是什么意思。可能您可以使用for循环进行如下迭代:

    for (var i=0, l=obj.length; i<l; ++i) {
      var item = obj[i];
    }
    
    for(var i=0,l=obj.length;i0&&!(obj中的(l-1))返回false;
    //更完整的检查(可选)
    
    对于(var i=0;i我说没有什么比扩展本机对象的简单性和表达性更好的了:

    // 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;        
    }
    
    Object.prototype.isArrayLike         = function(){ return false; };
    Array.prototype.isArrayLike          = function(){ return true; };
    NodeList.prototype.isArrayLike       = function(){ return true; };
    HTMLCollection.prototype.isArrayLike = function(){ return true; };
    

    这种方法可能会导致框架之间发生冲突,但是,我建议您与
    isArrayLike
    函数与名称不符的框架保持距离。

    可以在此处使用此函数检查对象是否与数组相似,即使其中没有元素:

    isArrayLike = function (_) {
    
        _[0] = 0; return [].slice.call(_).length >= Object.values(_).length;
    }
    
    这使用了我意外发现的一个小技巧,可以让你确定一个对象是(1)数组,(2)类似数组,还是(3)类似对象/对象


    唯一的缺点是,对于添加了类似对象属性的数组类,例如
    参数

    您可以检查对象是否可编辑:

    但是要小心,为字符串返回true。如果这是一个问题,请排除它们:

    function isIterable(o){
     return (o!=null && typeof(o[Symbol.iterator])==='function' && typeof(o)!=='string');
    }
    
    然后,使用迭代器访问元素,或者如果要使用常规数组[0]方式,只需添加一个长度检查属性即可


    完成类似isArrayLike的函数:

    function isArrayLike(a){
     return (
      a!=null &&
      typeof(a[Symbol.iterator])==='function' &&
      typeof(a.length)==='number' &&
      typeof(a)!=='string'
     );
    }
    
    从技术上讲,(几乎)根据标准(),每个对象都是“类似数组的”(因为
    未定义的
    的类型强制):

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

  • (obj)
  • 如果未传递elementTypes,则让elementTypes为(未定义、Null、布尔、字符串、符号、数字、对象)
  • 如果(obj) 不是对象,抛出类型错误
  • 设len为((obj,
    “length”
    ))
  • (len)
  • 让列表为空
  • 设索引为0

  • 在index时重复,我编写了这个函数,因为我需要在旧浏览器中工作的东西

    function isArrayLike(object) {
        var length
        if (object==null) {// same as object==undefined
            return false
        }
    
        try {// This throws an error in old browsers
            return typeof object[Symbol.iterator]=="function"
        }
        catch (e) {
            // Check that object.length is a non-negative integer
            return (length=object.length)===Math.abs(length|0)
                // And when non-zero check that length-1 is in object
                && (typeof object=="string" || !length || length-1 in object)
        }
    }
    

    检查是否存在<代码>(0)< /代码>?但是空数组可能失败。考虑到,但是我的函数可以通过一个空数组。字符串也可以使用方括号,你只指字符串中的一个字符。不确定是否考虑字符串是数组(不)。DOM元素与数组不同,但节点列表与数组不同。也许你可以坚持你的函数总是像数组一样传递,希望是最好的:)我将带有整数id的对象存储在数组中,id作为数组索引。由于这些数据来自于从1开始对记录进行编号的数据库,因此索引0处没有元素,即使长度大于0。我使用数组而不是对象,因为有时我喜欢使用数组方法,如
    .filter()
    。我的阵列将无法通过你的检查。似乎函数的第一行应该包含对数组的
    项实例的检查
    
    function isArrayLike(object) {
        var length
        if (object==null) {// same as object==undefined
            return false
        }
    
        try {// This throws an error in old browsers
            return typeof object[Symbol.iterator]=="function"
        }
        catch (e) {
            // Check that object.length is a non-negative integer
            return (length=object.length)===Math.abs(length|0)
                // And when non-zero check that length-1 is in object
                && (typeof object=="string" || !length || length-1 in object)
        }
    }