如何检查变量是否为JavaScript中的数组?[重复]

2020/09/15 15:31 · javascript ·  · 0评论

我想检查一个变量在JavaScript中是数组还是单个值。

我找到了可能的解决方案...

if (variable.constructor == Array)...

这是最好的方法吗?

有几种检查变量是否为数组的方法。最好的解决方案是您选择的解决方案。

variable.constructor === Array

这是在Chrome以及所有其他浏览器上最快的方法。所有数组都是对象,因此检查JavaScript引擎的构造函数属性是一个快速过程。

如果在确定对象属性是否为数组时遇到问题,则必须首先检查该属性是否存在。

variable.prop && variable.prop.constructor === Array

其他一些方法是:

Array.isArray(variable)

更新2019年5月23日使用Chrome 75,喊出@AnduAndrici邀请我与他的问题重温这段
最后一项是,在我看来最丑陋的,它是对一个
最慢的速度最快。作为第一个示例,运行速度约为1/5。这个家伙慢了大约2%到5%,但这很难说。牢固使用!结果给人留下了深刻的印象。Array.prototype实际上是一个数组。您可以在这里阅读有关它的更多信息https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray

variable instanceof Array

作为第一个示例,此方法的运行速度约为1/3如果您只关注漂亮的代码,而不是关注太多性能,那么它仍然很坚固,看上去更干净。请注意,检查数字并不variable instanceof Number总是返回false更新:instanceof现在速度提高了2/3!

所以又一次更新

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

这个家伙是最慢的尝试检查数组的人。但是,这是您要寻找的任何类型的一站式商店。但是,由于您正在寻找数组,因此请使用上面最快的方法。

另外,我进行了一些测试:http : //jsperf.com/instanceof-array-vs-array-isarray/35因此,请找点乐子并检查一下。

注意:由于jsperf.com关闭,@ EscapeNetscape创建了另一个测试。http://jsben.ch/#/QgYAV我想确保只要jsperf再次联机,原始链接都会保留。

您还可以使用:

if (value instanceof Array) {
  alert('value is Array!');
} else {
  alert('Not an array');
}

在我看来,这是一个非常优雅的解决方案,但对每个人来说都是如此。

编辑:

从ES5开始,现在还有:

Array.isArray(value);

但这将在较旧的浏览器上中断,除非您使用的是polyfill(基本上是IE8或类似版本)。

有多种解决方案,各有其独特之处。该页面提供了很好的概述。一种可能的解决方案是:

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

我注意到有人提到jQuery,但我不知道有一个isArray()函数。事实证明,它是在1.3版中添加的。

jQuery按照Peter的建议实现了它:

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

已经对jQuery抱有很大的信心(尤其是他们的跨浏览器兼容性技术),我将升级到1.3版并使用其功能(假设升级不会引起太多问题),或者直接在本人中使用此建议的方法码。

非常感谢您的建议。

在现代浏览器(和某些旧版浏览器)中,您可以

Array.isArray(obj)

Chrome 5,Firefox 4.0,IE 9,Opera 10.5和Safari 5支持)

如果需要支持旧版本的IE,则可以使用es5-shim填充 Array.isArray; 或添加以下内容

# only implement if no native implementation is available
if (typeof Array.isArray === 'undefined') {
  Array.isArray = function(obj) {
    return Object.prototype.toString.call(obj) === '[object Array]';
  }
};

如果使用jQuery,则可以使用jQuery.isArray(obj)$.isArray(obj)如果使用下划线,则可以使用_.isArray(obj)

如果您不需要检测在不同框架中创建的数组,也可以使用 instanceof

obj instanceof Array

注意arguments可以用来访问函数参数关键字不是数组,即使它(通常)的行为类似于:

var func = function() {
  console.log(arguments)        // [1, 2, 3]
  console.log(arguments.length) // 3
  console.log(Array.isArray(arguments)) // false !!!
  console.log(arguments.slice)  // undefined (Array.prototype methods not available)
  console.log([3,4,5].slice)    // function slice() { [native code] } 
}
func(1, 2, 3)

这是一个古老的问题,但是遇到同样的问题,我找到了一个非常优雅的解决方案,我想与他人分享。

向Array添加原型可以使其非常简单

Array.prototype.isArray = true;

现在,如果您有一个对象,则需要测试以查看其是否为数组,只需检查新属性即可

var box = doSomething();

if (box.isArray) {
    // do something
}

isArray仅在其数组时可用

通过克罗克福德

function typeOf(value) {
    var s = typeof value;
    if (s === 'object') {
        if (value) {
            if (value instanceof Array) {
                s = 'array';
            }
        } else {
            s = 'null';
        }
    }
    return s;
}

Crockford提到的主要失败之处是无法正确确定在不同上下文中创建的数组,例如window如果这还不够的话,该页面的版本要复杂得多。

我个人喜欢Peter的建议:https : //stackoverflow.com/a/767499/414784(对于ECMAScript3。对于ECMAScript 5,请使用Array.isArray()

但是,该帖子上的评论表明,如果toString()完全更改,则检查数组的方法将失败。如果您确实想具体说明并确保toString()未更改,并且objects类属性([object Array]是数组对象的类属性)没有问题,那么我建议您执行以下操作:

//see if toString returns proper class attributes of objects that are arrays
//returns -1 if it fails test
//returns true if it passes test and it's an array
//returns false if it passes test and it's not an array
function is_array(o)
{
    // make sure an array has a class attribute of [object Array]
    var check_class = Object.prototype.toString.call([]);
    if(check_class === '[object Array]')
    {
        // test passed, now check
        return Object.prototype.toString.call(o) === '[object Array]';
    }
    else
    {
        // may want to change return value to something more desirable
        return -1; 
    }
}

请注意,在《 JavaScript最终指南》第6版7.10中,它说Array.isArray()Object.prototype.toString.call()在ECMAScript 5中实现的。还请注意,如果您要担心toString()的实现发生变化,那么您还应该担心其他所有内置方法也会发生变化。为什么要使用push()有人可以更改!这种方法很愚蠢。上面的检查是为那些担心toString()更改的人提供的解决方案,但是我认为检查是不必要的。

如果您只处理EcmaScript 5及更高版本,则可以使用内置Array.isArray函数

例如,

Array.isArray([])    // true
Array.isArray("foo") // false
Array.isArray({})    // false

当我发布此问题时,我使用的JQuery版本未包含isArray函数。如果有的话,我可能会相信它是实现此特定类型检查的独立于浏览器的最佳方式,因此相信它。

由于JQuery现在确实提供了此功能,所以我会一直使用它...

$.isArray(obj);

(从1.6.2版开始)仍然可以通过以下形式对字符串进行比较来实现

toString.call(obj) === "[object Array]"

以为我会为可能已经在其脚本中使用Underscore.js库的用户添加另一个选项。Underscore.js具有isArray()函数(请参见http://underscorejs.org/#isArray)。

_.isArray(object) 

如果object是Array,则返回true。

如果您使用的是Angular,则可以使用angular.isArray()函数

var myArray = [];
angular.isArray(myArray); // returns true

var myObj = {};
angular.isArray(myObj); //returns false

http://docs.angularjs.org/api/ng/function/angular.isArray

在Crockford的JavaScript The Good Parts中,有一个函数来检查给定的参数是否为数组:

var is_array = function (value) {
    return value &&
        typeof value === 'object' &&
        typeof value.length === 'number' &&
        typeof value.splice === 'function' &&
        !(value.propertyIsEnumerable('length'));
};

他解释说:

首先,我们询问该值是否真实。我们这样做是为了拒绝null和其他虚假值。其次,我们询问typeof值是否为“对象”。对于对象,数组和(奇怪)为null都是如此。第三,我们询问该值是否具有为数字的length属性。对于数组,这始终是正确的,但对于对象通常不是如此。第四,我们询问该值是否包含一个拼接方法。这同样适用于所有阵列。最后,我们询问length属性是否可枚举(长度是否由for in循环产生?)。这对于所有数组都是错误的。这是我发现的最可靠的阵列测试。不幸的是,它是如此复杂。

通用解决方案如下:

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

从ECMAScript 5开始,一个正式的解决方案是:

Array.isArray(arr)

另外,对于旧的JavaScript库,虽然不够准确,但您可以找到以下解决方案:

var is_array = function (value) {
    return value &&
    typeof value === 'object' &&
    typeof value.length === 'number' &&
    typeof value.splice === 'function' &&
    !(value.propertyIsEnumerable('length'));
};

解决方案来自http://www.pixelstech.net/topic/85-How-to-check-wh是否an-object-is-an-array-or-not-in-JavaScript

https://github.com/miksago/Evan.js/blob/master/src/evan.js引用的代码

  var isArray = Array.isArray || function(obj) {
    return !!(obj && obj.concat && obj.unshift && !obj.callee);};

我正在使用以下代码行:

if (variable.push) {
   // variable is array, since AMAIK only arrays have push() method.
}

对于那些编码高尔夫的人来说,这是一个最少字符的不可靠测试:

function isArray(a) {
  return a.map;
}

在遍历/展平层次结构时通常使用以下方法:

function golf(a) {
  return a.map?[].concat.apply([],a.map(golf)):a;
}

input: [1,2,[3,4,[5],6],[7,[8,[9]]]]
output: [1, 2, 3, 4, 5, 6, 7, 8, 9]

w3schools

function isArray(myArray) {
    return myArray.constructor.toString().indexOf("Array") > -1;
}

我喜欢Brian的答案:

function is_array(o){
    // make sure an array has a class attribute of [object Array]
    var check_class = Object.prototype.toString.call([]);
    if(check_class === '[object Array]')    {
        // test passed, now check
        return Object.prototype.toString.call(o) === '[object Array]';
    } else{
        // may want to change return value to something more desirable
        return -1; 
    }
}

但您可以这样做:

return Object.prototype.toString.call(o) === Object.prototype.toString.call([]);

我创建了这段代码,可以返回真实类型。

我还不确定性能,但这是尝试正确识别typeof。

https://github.com/valtido/better-typeOf在这里也对此发表了一些博客http://www.jqui.net/jquery/better-typeof-than-the-javascript-native-typeof/

它的工作原理类似于当前的typeof。

var user = [1,2,3]
typeOf(user); //[object Array]

它认为可能需要进行一些微调,并考虑到一些问题,我还没有遇到或对其进行适当的测试。因此,无论是从性能角度还是错误地重新导入typeOf,都欢迎进一步改进。

我认为使用myObj.constructor == Object和myArray.constructor == Array是最好的方法。它比使用toString()快20倍。如果您使用自己的构造函数扩展对象,并且希望将这些创建也视为“对象”,那将不起作用,但否则会更快。typeof与构造方法一样快,但是typeof [] =='object'返回true,这通常是不希望的。 http://jsperf.com/constructor-vs-tostring

需要注意的一件事是null.constructor将引发错误,因此如果您要检查null值,则必须首先执行if(testThing!== null){}

由于.length属性专用于javascript中的数组,因此您可以简单地说

obj.length === +obj.length // true if obj is an array

Underscorejs和其他几个库使用了这个简短的技巧。

我刚想出的东西:

if (item.length)
//This is an array
else
//not an array

本文地址:http://javascript.askforanswer.com/ruhejianchabianliangshifouweijavascriptzhongdeshuzuzhongfu.html
文章标签: ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!