代码之家  ›  专栏  ›  技术社区  ›  stpe

如何检测变量是否为数组

  •  97
  • stpe  · 技术社区  · 15 年前

    确定JavaScript中的变量是否为数组的最佳事实标准跨浏览器方法是什么?

    在网上搜索有许多不同的建议,有些是好的,有些是无效的。

    function isArray(obj) {
        return (obj && obj.length);
    }
    

    但是,请注意,如果数组为空,或者obj实际上不是数组但实现了长度属性,等等,会发生什么。

    那么,哪种实现在实际工作、跨浏览器和仍然高效运行方面是最好的呢?

    12 回复  |  直到 15 年前
        1
  •  165
  •   Christoph    15 年前

    JS中对象的类型检查是通过 instanceof

    obj instanceof Array
    

    如果对象跨帧边界传递,这将不起作用,因为每个帧都有自己的边界 Array 对象您可以通过检查内部 对象的属性。要获得它,请使用 Object.prototype.toString() (这由ECMA-262保证工作):

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

    这两种方法仅适用于实际数组,而不适用于类似数组的对象,如 arguments length 属性,我会像这样检查:

    typeof obj !== 'undefined' && obj !== null && typeof obj.length === 'number'
    

    请注意,字符串将通过此检查,这可能会导致问题,因为IE不允许通过索引访问字符串的字符。因此,您可能想要改变 typeof obj !== 'undefined' typeof obj === 'object' 排除类型不同于的基本体和主体对象的步骤 'object' 一起。这仍然会让字符串对象通过,这必须手动排除。

    在大多数情况下,您真正想知道的是是否可以通过数值索引在对象上迭代。因此,检查对象是否具有名为 0 相反,这可以通过以下检查之一完成:

    typeof obj[0] !== 'undefined' // false negative for `obj[0] = undefined`
    obj.hasOwnProperty('0') // exclude array-likes with inherited entries
    '0' in Object(obj) // include array-likes with inherited entries
    

    “强制转换到”对象对于类似数组的基本体(即字符串)来说是正常工作所必需的。

    下面是用于对JS阵列进行健壮检查的代码:

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

    和可重复(即非空)数组状对象:

    function isNonEmptyArrayLike(obj) {
        try { // don't bother with `typeof` - just access `length` and `catch`
            return obj.length > 0 && '0' in Object(obj);
        }
        catch(e) {
            return false;
        }
    }
    
        2
  •  44
  •   Joorren Andy E    5 年前

    ECMAScript第5版的推出为我们提供了最可靠的测试变量是否为数组的方法, Array.isArray() :

    Array.isArray([]); // true
    

    虽然这里接受的答案适用于大多数浏览器的框架和窗口, 它不适用于Internet Explorer 7及更低版本 因为 Object.prototype.toString 从其他窗口对数组调用将返回 [object Object] [object Array] . IE9似乎也回归到了这种行为(见下面更新的修复)。

    (function () {
        var toString = Object.prototype.toString,
            strArray = Array.toString(),
            jscript  = /*@cc_on @_jscript_version @*/ +0;
    
        // jscript will be 0 for browsers other than IE
        if (!jscript) {
            Array.isArray = Array.isArray || function (obj) {
                return toString.call(obj) == "[object Array]";
            }
        }
        else {
            Array.isArray = function (obj) {
                return "constructor" in obj && String(obj.constructor) == strArray;
            }
        }
    })();
    

    它不是完全牢不可破的,但只有努力打破它的人才能打破它。它解决了IE7和更低版本以及IE9中的问题。 The bug still exists in IE 10 PP2 ,但可能会在发布前修复。

    另外,如果你不确定这个解决方案,我建议你测试一下你的心内容和/或阅读博客文章。如果您不喜欢使用条件编译,还有其他可能的解决方案。

        3
  •  8
  •   Nosredna    15 年前

    Crockford在“好的部分”第106页有两个答案。第一个答案检查构造函数,但会在不同的帧或窗口中给出错误的否定。这是第二点:

    if (my_value && typeof my_value === 'object' &&
            typeof my_value.length === 'number' &&
            !(my_value.propertyIsEnumerable('length')) {
        // my_value is truly an array!
    }
    

    Crockford指出,该版本将识别 arguments

    他对这个问题的有趣讨论从第105页开始。

    还有更有趣的讨论(发布好的部分) here

    var isArray = function (o) {
        return (o instanceof Array) ||
            (Object.prototype.toString.apply(o) === '[object Array]');
    };
    

    所有的讨论让我永远不想知道某个东西是否是数组。

        4
  •  2
  •   Mario Menger    15 年前

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

    (摘自jQueryV1.3.2的代码片段-稍微做了调整,以便在上下文之外理解)

        5
  •  2
  •   razzed    15 年前

    从大师John Resig和jquery那里窃取:

    function isArray(array) {
        if ( toString.call(array) === "[object Array]") {
            return true;
        } else if ( typeof array.length === "number" ) {
            return true;
        }
        return false;
    }
    
        6
  •  1
  •   James Hugard    15 年前

    一旦确定该值是数组,您将如何处理它?

    例如,如果要枚举包含的值 与数组类似,或者如果它是一个用作哈希表的对象,那么下面的代码将得到您想要的(当闭包函数返回除“undefined”以外的任何内容时,此代码将停止。请注意,它不会在COM容器或枚举上迭代;这将留给读者作为练习):

    function iteratei( o, closure )
    {
        if( o != null && o.hasOwnProperty )
        {
            for( var ix in seq )
            {
                var ret = closure.call( this, ix, o[ix] );
                if( undefined !== ret )
                    return ret;
            }
        }
        return undefined;
    }
    

    (注意:“o!=null”测试用于null和未定义)

    使用示例:

    // Find first element who's value equals "what" in an array
    var b = iteratei( ["who", "what", "when" "where"],
        function( ix, v )
        {
            return v == "what" ? true : undefined;
        });
    
    // Iterate over only this objects' properties, not the prototypes'
    function iterateiOwnProperties( o, closure )
    {
        return iteratei( o, function(ix,v)
        {
            if( o.hasOwnProperty(ix) )
            {
                return closure.call( this, ix, o[ix] );
            }
        })
    }
    
        7
  •  1
  •   Daniel Worthington-Bodart    4 年前

    为什么不直接使用

    Array.isArray(variable)

    这是做这件事的标准方法(谢谢Karl)

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray

        8
  •  0
  •   Otto Allmendinger    15 年前

    如果您想要跨浏览器,您需要 jQuery.isArray .

        9
  •  0
  •   Eineki    15 年前

    在…上 w3school

    为了检查一个变量是否是数组,他们使用类似的方法

    function arrayCheck(obj) { 
        return obj && (obj.constructor==Array);
    }
    

    在Chrome、Firefox、Safari和ie7上测试

        10
  •  -2
  •   Tony Miller    15 年前

    PHPJS site . 您可以链接到软件包,也可以转到 function directly . 我强烈推荐该站点使用JavaScript构建良好的PHP函数等价物。

        11
  •  -2
  •   kuy    15 年前

    没有足够的构造函数引用。有时它们对构造函数有不同的引用。所以我用字符串表示它们。

    function isArray(o) {
        return o.constructor.toString() === [].constructor.toString();
    }
    
        12
  •  -4
  •   patrick72    9 年前

    Array.isArray(obj) 通过 obj.constructor==Array

    样品:

    Array('44','55').constructor==Array

    '55'.constructor==Array