ChatGPT解决这个技术问题 Extra ChatGPT

如何检查对象是否为数组? [复制]

这个问题在这里已经有了答案:How do I check if a variable is an array in JavaScript? (24 个回答) 9 个月前关闭。

我正在尝试编写一个接受字符串列表或单个字符串的函数。如果它是一个字符串,那么我想将它转换为一个只有一个项目的数组,这样我就可以循环它而不必担心出错。

那么如何检查变量是否为数组呢?

我以为您的意思是“检查对象是否为数组”,但您想专门检查“对象是字符串数组还是单个字符串”。不知道你看到了吗?还是只有我?我在想更像this的东西......我是不是在这里遗漏了什么?
TL;DR - arr.constructor === Array 最快。
jsben.ch/#/QgYAV - 最常用方法的基准
TL;DR - 数组。isArray(arr) 从 ES5 开始;和 $.isArray(arr) 在 jQuery 中。
请记住,如果您出于任何原因通过原型覆盖您的构造函数,则 arr.constructor === Array 测试将返回 false。 Array.isArray(arr) 仍然返回 true。

P
Peter Mortensen

ECMAScript 标准中给出的查找 Object 类的方法是使用 Object.prototype 中的 toString 方法。

if(Object.prototype.toString.call(someVar) === '[object Array]') {
    alert('Array!');
}

或者您可以使用 typeof 来测试它是否是 字符串

if(typeof someVar === 'string') {
    someVar = [someVar];
}

或者,如果您不关心性能,您可以对新的空数组执行 concat

someVar = [].concat(someVar);

还有可以直接查询的构造函数:

if (somevar.constructor.name == "Array") {
    // do something
}

查看 T.J. Crowder's 博客中的 a thorough treatment,正如他在下面的评论中所发布的那样。

查看 this benchmark 了解哪种方法效果更好:http://jsben.ch/#/QgYAV

对于所提出的问题,使用 ES6@Bharath 将字符串转换为数组:

const convertStringToArray = (object) => {
   return (typeof object === 'string') ? Array(object) : object
}

认为:

let m = 'bla'
let n = ['bla','Meow']
let y = convertStringToArray(m)
let z = convertStringToArray(n)
console.log('check y: '+JSON.stringify(y)) . // check y: ['bla']
console.log('check y: '+JSON.stringify(z)) . // check y: ['bla','Meow']

+1 是的,toString 是可行的方法之一。我在这里做了一点总结:blog.niftysnippets.org/2010/09/say-what.html
如果您不想输入“[object Array]”,请使用 Object.prototype.toString.call( someVar ) === Object.prototype.toString.call( [] ) 或创建一个方便的函数来获取类型'不想输入 Object.prototype.toString.call
我使用在“现代浏览器”(即 IE9+ 和其他所有浏览器)中工作的 vanilla Array.isArray。对于旧浏览器支持,请使用 MDN developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 的 shim
生活在现代世界 - Array.isArray(obj)
P
Peter Mortensen

在现代浏览器中,您可以:

Array.isArray(obj)

Supported by Chrome 5、Firefox 4.0、Internet Explorer 9、Opera 10.5 和 Safari 5)

为了向后兼容,您可以添加以下内容:

// 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)。如果您使用 Underscore.js,您可以使用 _.isArray(obj)

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

obj instanceof Array

以下是支持 Array.isArray 的浏览器的 more complete 列表
@NobleUplift:如果数组来自不同的框架,instanceof Array 将失败,因为来自不同框架的每个数组都有不同的 Array 构造函数和原型。出于兼容性/安全原因,每个框架都有自己的全局环境,其中包括全局对象。一帧的 Object 全局不同于另一帧的 Object 全局。 Array 全局变量也是如此。 Axel Rauschmayer talks more about this
请注意,截至 2022 年,这得到了很好的支持(甚至支持许多浏览器版本):caniuse.com/?search=isArray 现在也是最快的方法:jsben.ch/QgYAV
C
ChaosPandion

我将首先检查您的实现是否支持 isArray

if (Array.isArray)
    return Array.isArray(v);

您也可以尝试使用 instanceof 运算符

v instanceof Array

如果在另一个框架中创建了 vvthatFrame.contentWindow.Array 类的实例),v instanceof Array 将返回 false。
具体来说:Array.isArray 被定义为 ECMAScript 5/Javascript 1.8.5 的一部分。
A
Al Foиce ѫ

jQuery 还提供了一个 $.isArray() 方法:

var a = ["A", "AA", "AAA"]; if($.isArray(a)) { alert("a 是一个数组!"); } else { alert("a 不是数组!"); }


请注意,jQuery 在内部使用 toString 方法:GitHub Source
s
shinobi

这是所有方法中最快的(支持所有浏览器):

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

P
Peter Mortensen

假设您在下面有这个数组:

var arr = [1,2,3,4,5];

JavaScript(新旧浏览器):

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

或者

function isArray(arr) {
  return arr instanceof Array;
}

或者

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

然后像这样调用它:

isArray(arr);

JavaScript(Internet Explorer 9+、Chrome 5+、Firefox 4+、Safari 5+ 和 Opera 10.5+)

Array.isArray(arr);

jQuery:

$.isArray(arr);

角度:

angular.isArray(arr);

Underscore.js 和 Lodash

_.isArray(arr);

P
Peter Mortensen

Array.isArray 运行速度很快,但并非所有版本的浏览器都支持。

因此,您可以为其他人破例并使用通用方法:

    Utils = {};
    Utils.isArray = ('isArray' in Array) ?
        Array.isArray :
        function (value) {
            return Object.prototype.toString.call(value) === '[object Array]';
        }

P
Peter Mortensen

一个简单的功能来检查这个:

function isArray(object)
{
    return object.constructor === Array;
}

我会将其减少到一行 return object.constructor === Array - 但是您确定这只会对数组返回 true 吗?
可以用所有布尔表达式做到这一点。当我看到 if(x) return true; else return false 时让我发疯 :-) 即使它是倒退的,你也应该否定这个表达式。
如果对象未定义或为空,这将严重失败。
a
ajax333221

正如 MDN 所说的 in here

使用 Array.isArray 或 Object.prototype.toString.call 将常规对象与数组区分开来

像这样:

Object.prototype.toString.call(arr) === '[object Array]',或者

Array.isArray(arr)


V
Vikash Kumar

这个问题只有一个解决方案

x instanceof Array

其中 x 是变量,如果 x 是数组,它将返回 true,如果不是,则返回 false。


S
Safareli

您可以使用 Array.isArray()。这是一个polyfill:

if (Array.isArray == null) {
  Array.isArray = (arr) => Object.prototype.toString.call(arr) === "[object Array]"
}

你能详细说明一下吗?例如,为什么“=”的两边都是“Array.isArray”? “Array.isArray”是一种方法。工作原理是什么?请通过 editing (changing) your answer 回复,而不是在评论中(没有“编辑:”、“更新:”或类似内容 - 答案应该看起来好像是今天写的)。
A
Al Foиce ѫ

我会做一个函数来测试你正在处理的对象的类型......

function whatAmI(me){ return Object.prototype.toString.call(me).split(/\W/)[2]; } // 测试 console.log( whatAmI(["aiming","@"]), whatAmI({living:4,breathing:4}), whatAmI(function(ing){ return ing+" 到全局窗口" } ), whatAmI("要和你做什么?") ); // 输出:数组对象函数字符串

那么你可以写一个简单的if语句......

if(whatAmI(myVar) === "Array"){
    // do array stuff
} else { // could also check `if(whatAmI(myVar) === "String")` here to be sure
    // do string stuff
}

A
Ahmet DAL

您可以检查变量的类型是否为数组;

var myArray=[];

if(myArray instanceof Array)
{
....
}

一些人已经提到了instanceof ..我认为它在一些奇怪的情况下会失败。
P
Peter Mortensen

我以一种非常简单的方式做到这一点。这个对我有用。

Array.prototype.isArray = true;

a=[]; b={};
a.isArray  // true
b.isArray  // (undefined -> false)

{isArray:true}愚弄
JSON.parse(someDataFromElsewhere).items.isArray 可能返回 true(取决于数据)并破坏您的代码。
C
Community

考虑到评论,这是我对 this answer 进行改进的尝试:

var isArray = myArray && myArray.constructor === Array;

它摆脱了 if/else,并解释了数组为空或未定义的可能性


构造函数在 ES5 中不可用
l
le_top

我已经用两种替代方法以及错误检查更新了 jsperf fiddle

事实证明,在“Object”和“Array”原型中定义常量值的方法比任何其他方法都快。这是一个有点令人惊讶的结果。

/* 初始化 */ Object.prototype.isArray = function() { return false; }; Array.prototype.isArray = function() { return true; }; Object.prototype._isArray = false; Array.prototype._isArray = true; var arr = ["1", "2"]; var noarr = "1"; /* 方法一(函数) */ if (arr.isArray()) document.write("arr是根据函数的数组
"); if (!noarr.isArray()) document.write("noarr 根据函数不是数组
"); /* 方法 2 (value) - **** FASTEST ***** */ if (arr._isArray) document.write("arr 是一个根据成员值的数组
"); if (!noarr._isArray) document.write("noarr 根据成员值不是数组
");

如果变量采用未定义的值,则这两种方法不起作用,但如果您确定它们具有值,它们确实起作用。关于检查一个值是数组还是单个值时要考虑性能,第二种方法看起来是一种有效的快速方法。它比 Chrome 上的“instanceof”略快,是 Internet Explorer、Opera 和 Safari(在我的机器上)中第二好的方法的两倍。


P
Peter Mortensen

我知道,人们正在寻找某种原始的 JavaScript 方法。但是,如果您不想多想,请查看 Underscore.js' isArray

_.isArray(object)

如果 object 是 Array,则返回 true。

(function(){ return _.isArray(arguments); })();
=> false
_.isArray([1,2,3]);
=> true

“除非还包括框架/库的另一个标签,否则需要纯 JavaScript 答案。”
P
Peter Mortensen

最佳做法是使用 constructor 进行比较,类似这样

if(some_variable.constructor === Array){
  // do something
}

您也可以使用其他方法,例如 typeOf,将其转换为字符串然后进行比较,但将其与 dataType 进行比较始终是更好的方法。


P
Peter Mortensen

我见过的最好的解决方案是跨浏览器替换 typeof。检查Angus Croll's solution

TL;DR 版本在下面,但这篇文章对这个问题进行了很好的讨论,所以如果你有时间,你应该阅读它。

Object.toType = function(obj) {
    return ({}).toString.call(obj).match(/\s([a-z|A-Z]+)/)[1].toLowerCase();
}
// ... and usage:
Object.toType([1,2,3]); //"array" (all browsers)

// or to test...
var shouldBeAnArray = [1,2,3];
if(Object.toType(shouldBeAnArray) === 'array'){/* do stuff */};

T
Tim Down

如果可以传递给此函数的仅有两种值是字符串或字符串数组,请保持简单并使用 typeof 检查字符串的可能性:

function someFunc(arg) {
    var arr = (typeof arg == "string") ? [arg] : arg;
}

是的......这适用于这种情况,但不是一般情况下。最终还是使用了可变参数。 :)
n
namuol

这是我的懒惰方法:

if (Array.prototype.array_ === undefined) {
  Array.prototype.array_ = true;
}

// ...

var test = [],
    wat = {};

console.log(test.array_ === true); // true
console.log(wat.array_ === true);  // false

我知道“弄乱”原型是一种亵渎,但是it appears to perform significantly better than the recommended toString method

注意:这种方法的一个缺陷是它wont work across iframe boundaries,但对于我的用例来说,这不是问题。


它在性能方面不再更好了,至少在 Ubuntu 64 位的 FF30 上
wat = {array_: true} 个对象愚弄。
@Bergi:是的,这应该很明显。如果您设置 obj.array_ = true,那么您只是在自欺欺人
@namuol:我不一定在自欺欺人。经常有足够多的对象被用作字典。考虑使用搜索字符串作为属性键的 cache 对象来记忆搜索结果。如果用户搜索 array_ 会怎样?你的对象会因此变成一个数组吗?这只是一个错误。
@namuol:此外,这种方法需要所有相关方(包括使用的库)都同意 .array_ 用于标记数组。实际情况并非如此,.array 可以表示任何含义。您至少应该使用一个描述性的字符串,并表明任意使用的不恰当性,例如使用 .__isArray = true
m
mpen

这个函数将几乎任何东西变成一个数组:

function arr(x) {
    if(x === null || x === undefined) {
        return [];
    }
    if(Array.isArray(x)) {
        return x;
    }
    if(isString(x) || isNumber(x)) {
        return [x];
    }
    if(x[Symbol.iterator] !== undefined || x.length !== undefined) {
        return Array.from(x);
    }
    return [x];
}

function isString(x) {
    return Object.prototype.toString.call(x) === "[object String]"
}

function isNumber(x) {
    return Object.prototype.toString.call(x) === "[object Number]"
}

它使用了一些较新的浏览器功能,因此您可能需要对其进行 polyfill 以获得最大支持。

例子:

> arr(null);
[]
> arr(undefined)
[]
> arr(3.14)
[ 3.14 ]
> arr(1/0)
[ Infinity ]
> gen = function*() { yield 1; yield 2; yield 3; }
[Function: gen]
> arr(gen())
[ 1, 2, 3 ]
> arr([4,5,6])
[ 4, 5, 6 ]
> arr("foo")
[ 'foo' ]

NB 字符串将被转换为具有单个元素的数组,而不是字符数组。删除 isString 检查您是否更喜欢它。

我在这里使用了 Array.isArray,因为它是 most robust,而且也是最简单的。


J
Jan Aagaard

如果您知道您的对象没有 concat 方法,则可以使用以下内容。

var arr = []; if (typeof arr.concat === 'function') { console.log("这是一个数组"); }


这是一个很好的技巧,但可以被覆盖......但大多数时候应该得到结果
V
Vadim Kotov
var a = [], b = {};

console.log(a.constructor.name == "Array");
console.log(b.constructor.name == "Object");

你好,谢谢你的回答。仅代码的答案往往被忽略,您介意为您的代码添加一些解释吗?
P
Peter Mortensen

在 Stoyan Stefanov 的书 JavaScript Patterns 中有一个很好的例子,它应该处理所有可能的问题以及使用 ECMAScript 5 方法 Array.isArray()

所以这里是:

if (typeof Array.isArray === "undefined") {
    Array.isArray = function (arg) {
        return Object.prototype.toString.call(arg) === "[object Array]";
    };
}

顺便说一句,如果你使用 jQuery,你可以使用它的方法 $.isArray()


+1:为什么不只是一个简单的 if(!Array.isArray) {...
P
Peter Mortensen

您可以使用 isArray 方法,但我更愿意检查:

Object.getPrototypeOf(yourvariable) === Array.prototype


你为什么更喜欢这个?
@mpen Object.getPrototypeOf(yourvariable) 它返回一个 Array 对象的原型。并且该代码是最快且安全的依赖。
很容易挫败:pastebin.com/MP8d5bCE另外,您是否有性能测试来支持您的“最快”声明?
R
RoboTamer
function isArray(value) {
    if (value) {
        if (typeof value === 'object') {
            return (Object.prototype.toString.call(value) == '[object Array]')
        }
    }
    return false;
}

var ar = ["ff","tt"]
alert(isArray(ar))

一个解释将是有序的。请通过 editing (changing) your answer 回复,而不是在评论中(没有“编辑:”、“更新:”或类似内容 - 答案应该看起来好像是今天写的)。
B
Brad Parks

用于测试输入值是否为数组的简单函数如下:

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

这适用于跨浏览器,也适用于旧版浏览器。这是pulled from T.J. Crowders' blog post


M
Michał Perłakowski

你可以试试这个:

var arr = []; (or) arr = new Array();
var obj = {}; (or) arr = new Object();

arr.constructor.prototype.hasOwnProperty('push') //true

obj.constructor.prototype.hasOwnProperty('push') // false

k
kolyaseg

在您的情况下,您可以使用 Arrayconcat 方法,它可以接受单个对象以及数组(甚至组合):

function myFunc(stringOrArray)
{
  var arr = [].concat(stringOrArray);

  console.log(arr);

  arr.forEach(function(item, i)
  {
    console.log(i, "=", item);
  })
}

myFunc("one string");

myFunc(["one string", "second", "third"]);

concat 似乎是最古老的 Array 方法之一(即使 IE 5.5 也很清楚)。