¿Cómo verificar si un objeto es una matriz?


2754

Estoy tratando de escribir una función que acepte una lista de cadenas o una sola cadena. Si es una cadena, entonces quiero convertirla en una matriz con solo un elemento, para poder recorrerla sin temor a un error.

Entonces, ¿cómo verifico si la variable es una matriz?


He redondeado las diversas soluciones a continuación y he creado una prueba jsperf . Todos son rápidos, así que solo úselos Array.isArray, ahora está bien soportado y funciona en todos los marcos .


66
Pensé que querías decir 'verificar si el objeto es una matriz', pero quieres verificar si 'el objeto es una matriz de cadenas o una sola cadena' específicamente. ¿No estás seguro si lo ves? O solo soy yo? Estaba pensando en algo más como esto ... ¿Me estoy perdiendo algo aquí?
rr1g0

149
TL; DR : arr.constructor === Arrayes el más rápido.
Neta

3
jsben.ch/#/QgYAV - un punto de referencia para las formas más comunes
EscapeNetscape

39
TL; DR - Matriz. isArray (arr) desde ES5; y $. isArray (arr) en jQuery.
Ondra Žižka

66
Solo tenga en cuenta que si por alguna razón sobrescribe su constructor a través de un prototipo, esa arr.constructor === Arrayprueba devolverá falso. Array.isArray(arr)todavía devuelve cierto sin embargo.
ghaschel

Respuestas:


979

En los navegadores modernos puedes hacer

Array.isArray(obj)

( Compatible con Chrome 5, Firefox 4.0, IE 9, Opera 10.5 y Safari 5)

Para compatibilidad con versiones anteriores, puede agregar lo siguiente

# 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]';
  }
};

Si usa jQuery puede usar jQuery.isArray(obj)o $.isArray(obj). Si usa guión bajo, puede usar_.isArray(obj)

Si no necesita detectar arreglos creados en diferentes marcos, también puede usar instanceof

obj instanceof Array

99
Aquí hay una lista más completa de navegadores compatiblesArray.isArray
lightswitch05

if (typeof Array.isArray === 'undefined') {podría cambiarse aif(!Array.isArray) {
iMatoria

Por lo que vale Object.prototype.string.call(obj)se puede suplantar si el objeto lo tiene Symbol.toStringTag. Dicho esto, no conozco ningún entorno que se envíe, Symbol.toStringTagpero no Array.isArrayasí, esto parece seguro.
Benjamin Gruenbaum

55
¿Por qué instanceof Arrayfalla si la matriz es de un marco diferente?
NobleUplift

16
@NobleUplift: instanceof Arrayfalla si la matriz es de un marco diferente porque cada matriz de ese marco diferente tiene un Arrayconstructor y un prototipo diferentes . Por razones de compatibilidad / seguridad, cada marco tiene su propio entorno global, y esto incluye objetos globales. Lo Objectglobal de un marco es diferente de lo Objectglobal de otro. Así también para los Arrayglobales. Axel Rauschmayer habla más sobre esto .
jschoi

1943

El método dado en el estándar ECMAScript para encontrar la clase de Objeto es usar el toStringmétodo desde Object.prototype.

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

O podría usar typeofpara probar si es una cadena:

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

O si no está preocupado por el rendimiento, puede simplemente hacer una concata una nueva matriz vacía.

someVar = [].concat( someVar );

También está el constructor que puede consultar directamente:

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

Echa un vistazo a un tratamiento exhaustivo del blog de @TJ Crowder , como se publica en su comentario a continuación.

Consulte este punto de referencia para tener una idea de qué método funciona mejor: http://jsben.ch/#/QgYAV

De @Bharath convierte una cadena a una matriz usando Es6 para la pregunta formulada:

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

suponer:

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']

65
+1 Sí, toStringes una de las formas de ir. Hago un breve
TJ Crowder

3
typeof new String('beans') > 'objeto'
Ben

16
Si no desea escribir "[matriz de objetos]", use Object.prototype.toString.call (someVar) === Object.prototype.toString.call ([]) o realice una función conveniente para obtener el tipo si no lo hace no quiero escribir Object.prototype.toString.call
Pramod

13
Yo uso el Vanilla Array.isArray que funciona en 'navegadores modernos' (es decir, IE9 + y todos los demás). Y para la compatibilidad con navegadores antiguos, use el shim de MDN developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
David Gilbertson

21
Vive en el mundo moderno -Array.isArray(obj)
mcfedr

1274

Primero verificaría si su implementación admite isArray:

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

También puedes intentar usar el instanceofoperador

v instanceof Array

127
v instanceof Arraydevolverá falso si vse creó en otro marco ( ves una instancia de thatFrame.contentWindow.Arrayclase).
pepkin88

47
Para ser específico: Array.isArrayse define como parte de ECMAScript 5 / Javascript 1.8.5.
jevon

8
Solución realmente simple y ordenada PERO isArray no es compatible con algunos navegadores más antiguos (ex IE7 e IE8). Fuente: kangax.github.io/es5-compat-table/#
Wookie88

2
¿Qué tal si if (Array.isArray) devuelve Array.isArray (v); else return v instanceof Array;
lewdev

1
o simplemente:return (Array.isArray && Array.isArray(v)) || (v instanceof Array);
Stijn de Witt

298

jQuery también ofrece un $.isArray()método:

var a = ["A", "AA", "AAA"];

if($.isArray(a)) {
  alert("a is an array!");
} else {
  alert("a is not an array!");
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


27
Solo una nota, jQuery utiliza el método toString internamente: Fuente GitHub
Jacob Squires

55
@JacobSquires depende. Acabo de probar aquí, la última jQuery en Chrome, $.isArray === Array.isArrayestá volviendo verdadera.
Renan

3
@ Renan: Esto es lo bueno de usar jQuery. Por lo general, utiliza el método más moderno y mejor para hacerlo, y no tiene que hacer todas las funciones comprobándose usted mismo para saber qué usar.
temor

jQuery está utilizando Array.isArraydetrás de escena: github.com/jquery/jquery/blob/master/src/core.js#L211
Sergiu

1
Pero nadie va a usar jQuery SOLO PARA esta funcionalidad, ¿verdad? No solo descargaría jquery porque quiero verificar si algo es una matriz: p
Automagisch

106

Este es el más rápido entre todos los métodos (todos los navegadores compatibles):

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

2
Tienes razón, eso es lo más rápido según las pruebas que incluí en la pregunta.
mpen

55
¿Hay alguna desventaja al usar este método? Parece mucho más simple y efectivo que la respuesta superior aceptada.
David Meza

@shinobi - solo curiosidad (y he visto esto a menudo) - ¿por qué expresas la condición if (obj && Array === obj.constructor)en lugar de if (obj && obj.constructor === Array)? ¿Se pierde en la traducción al inglés y luego en el código? por ejemplo, los angloparlantes generalmente preguntan "¿existe el objeto, y su constructor proviene de la clase de matriz?", por lo que el flujo de código al leerlo es más lógico. o hay alguna razón técnica?
sincronización

function object_type(o){var t = typeof(o);return ((t==="object") && (o.constructor===Array)) ? "array" : t;} /*allows you to */ switch(object_type(o)){ case 'array': break; case 'object' : o.dosomething();}
sincronizar el

3
@shinobi todo bien. supongo que podría ser una resaca de un hábito seguro de c: si accidentalmente usa = en lugar de ==, no se compilaría ya que no es una variable asignable.
sincronización

47

Imagina que tienes esta matriz a continuación :

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

Javascript (navegadores nuevos y antiguos):

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

o

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

o

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

entonces llámalo así:

isArray(arr);

Javascript (IE9 +, Ch5 +, FF4 +, Saf5 +, Opera10.5 +)

Array.isArray(arr);

jQuery:

$.isArray(arr);

Angular:

angular.isArray(arr);

Subrayar y Lodash:

_.isArray(arr);

34

Array.isArray funciona rápido, pero no es compatible con todas las versiones de navegadores. Por lo tanto, puede hacer una excepción para los demás y utilizar el método universal:

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

3
Necesitas obtener el .toString()método Object.prototype. En este momento estás usando el window.toString(), que no es lo mismo.
el sistema

Tienes razón. window.toStringhaz lo mismo que Object.prototype.toStringsolo en Chrome.
CruorVult

isArray no es rápido en absoluto. Es el método más lento.
jemiloii

¿Por qué no solo agregarlo a Array en lugar de a Utils? (Sé que no desea propiedades adicionales en nuevos objetos de matriz, pero creo que eso solo sucede si agrega isArray a Array.prototype.)
David Winiecki

27

Función simple para verificar esto:

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

16
Lo reduciría a una línea return object.constructor === Array, pero ¿estás seguro de que esto solo será cierto para las matrices?
mpen

12
Puede hacer eso con todas las expresiones booleanas. Me if(x) return true; else return falsevuelve loco cuando veo :-) Incluso si es al revés, debes negar la expresión.
mpen

3
La razón por la que esto no devuelve verdadero para getElementsByTagName, es porque el resultado de esa función es en realidad una colección HTMLC y no una matriz.
Yuval A.

66
Esto falla gravemente si el objeto no está definido o es nulo.
John Henckel

1
@JohnHenckel Vea mi respuesta stackoverflow.com/a/29400289/34806 toma en cuenta tanto su preocupación como el primer comentario, todo en una línea
Dexygen,

17

Como dice MDN aquí :

use Array.isArray u Object.prototype.toString.call para diferenciar objetos regulares de matrices

Me gusta esto:

  • Object.prototype.toString.call(arr) === '[object Array]'o

  • Array.isArray(arr)


17

Solo hay una solución de línea para esta pregunta

x instanceof Array

donde x es la variable, devolverá verdadero si x es una matriz y falso si no lo es.


¡Mucho más limpio y seguro para el futuro! Esto o una typeofcomparación.
ChristoKiwi

¿Es esto algo que recibe una buena cantidad de soporte de navegador? Me gusta.
Dan Zuzevich

1
Desafortunadamente, esto no es realmente útil sin un try / catch porque si "x" es un objeto como {}una matriz, entonces se obtiene un error de sintaxis.
abalter

15

Puede verificar el tipo de su variable si es una matriz con;

var myArray=[];

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

1
Algunas personas ya han mencionado instanceof... Creo que falla bajo algunos escenarios extraños.
mpen

15

Haría una función para probar el tipo de objeto con el que está tratando ...

function whatAmI(me){ return Object.prototype.toString.call(me).split(/\W/)[2]; }

// tests
console.log(
  whatAmI(["aiming","@"]),
  whatAmI({living:4,breathing:4}),
  whatAmI(function(ing){ return ing+" to the global window" }),
  whatAmI("going to do with you?")
);

// output: Array Object Function String

entonces puedes escribir una declaración if simple ...

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

12

Hago esto de una manera muy simple. Funciona para mi. ¿Algún inconveniente?

Array.prototype.isArray = true;

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

77
engañado por{isArray:true}
Bergi

JSON.parse(someDataFromElsewhere).items.isArraypodría devolver verdadero (dependiendo de los datos) y romper su código.
Roy Tinker

12

Este es mi intento de mejorar esta respuesta teniendo en cuenta los comentarios:

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

Elimina el if / else, y explica la posibilidad de que la matriz sea nula o indefinida


constructor no está disponible en ES5
TechTurtle


11

He actualizado el violín jsperf con dos métodos alternativos, así como la comprobación de errores.

Resulta que el método que define un valor constante en los prototipos 'Objeto' y 'Matriz' es más rápido que cualquiera de los otros métodos. Es un resultado algo sorprendente.

/* Initialisation */
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";

/* Method 1 (function) */
if (arr.isArray()) document.write("arr is an array according to function<br/>");
if (!noarr.isArray()) document.write("noarr is not an array according to function<br/>");
/* Method 2 (value) - **** FASTEST ***** */
if (arr._isArray) document.write("arr is an array according to member value<br/>");
if (!noarr._isArray) document.write("noarr is not an array according to member value<br/>");

Estos dos métodos no funcionan si la variable toma el valor indefinido, pero funcionan si está seguro de que tienen un valor. Con respecto a la verificación teniendo en cuenta el rendimiento si un valor es una matriz o un valor único, el segundo método parece un método rápido válido. Es ligeramente más rápido que 'instanceof' en Chrome, dos veces más rápido que el segundo mejor método en Internet Explorer, Opera y Safari (en mi máquina).


9

Sé que la gente está buscando algún tipo de enfoque de JavaScript sin formato. Pero si quiere pensar menos, eche un vistazo aquí: http://underscorejs.org/#isArray

_.isArray(object) 

Devuelve verdadero si el objeto es una matriz.

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

77
"A menos que también se incluya otra etiqueta para un marco / biblioteca, se espera una respuesta pura de JavaScript".
Michał Perłakowski

5

La mejor solución que he visto es un reemplazo entre navegadores para typeof. Comprueba la solución de Angus Croll aquí .

La versión TL; DR está a continuación, pero el artículo es una gran discusión sobre el tema, por lo que debe leerlo si tiene tiempo.

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 */};

5

Aquí está mi enfoque perezoso:

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

// ...

var test = [],
    wat = {};

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

Sé que es un sacrilegio "meterse" con el prototipo, pero parece funcionar significativamente mejor que el toStringmétodo recomendado .

Nota: Una trampa de este enfoque es que no funcionará más allá de los iframelímites , pero para mi caso de uso esto no es un problema.


ya no es mejor en términos de rendimiento, al menos en FF30 en Ubuntu de 64 bits
test30

2
engañado por los wat = {array_: true}objetos.
Bergi

@ Bergi: Sí, eso debería ser obvio. Si estás configurando obj.array_ = true, entonces solo te estás engañando a ti mismo .
namuol

@namuol: No necesariamente me estoy engañando a mí mismo. A menudo se utilizan suficientes objetos como diccionarios. Piense en un cacheobjeto para memorizar resultados de búsqueda que use las cadenas de búsqueda como claves de propiedad. ¿Qué pasa si un usuario busca array_? ¿Su objeto se convierte en una matriz debido a eso? Es solo un error.
Bergi

@namuol: Además, este enfoque requeriría que todas las partes involucradas (incluidas las bibliotecas usadas) puedan aceptar que .array_se usa para etiquetar matrices. Ese no es realmente el caso aquí, .arraypuede significar cualquier cosa. Al menos debe usar una cadena descriptiva y señalar la inadecuación del uso arbitrario, por ejemplo, con .__isArray = true.
Bergi

5

Hay un buen ejemplo en el libro Patrones JavaScript de Stoyan Stefanov que supone manejar todos los problemas posibles y utilizar el método ECMAScript 5 Array.isArray () .

Asi que aqui esta:

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

Por cierto, si está usando jQuery, puede usar su método $ .isArray ()


2
+1: ¿por qué no solo un simple if(!Array.isArray) {...?
Marco Demaio

5

La forma más fácil y rápida de verificar si un objeto es una matriz o no.

 var arr = [];
  arr.constructor.name ==='Array'  //return true;

o

arr.constructor ===Array //return true;

o puedes hacer una función de utilidad:

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

uso:

isArray(arr); //return true

5

Lo siguiente podría usarse si sabe que su objeto no tiene un método concat.

var arr = [];
if (typeof arr.concat === 'function') {
    console.log("It's an array");
}


Este es un buen truco, pero podría ser anulado ... pero la mayoría de las veces debería obtener el resultado
Alireza

5

Podrías es el método de matriz, pero preferiría consultar con

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


¿Por qué preferirías esto?
mpen

@mpen Object.getPrototypeOf(yourvariable)devuelve el prototipo de un objeto Array. Y el código es más rápido y seguro.
STEEL

1
Es fácil frustrar: pastebin.com/MP8d5bCE Además, ¿tiene pruebas de rendimiento para respaldar su reclamo "más rápido"?
mpen

4

Si los únicos dos tipos de valores que podrían pasarse a esta función son una cadena o una matriz de cadenas, manténgalo simple y use una typeofverificación para la posibilidad de la cadena:

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

Sí ... eso funcionaría para este escenario, pero no en general. Terminé usando varargs de todos modos. :)
mpen

4
A = [1,2,3]
console.log(A.map==[].map)

En la búsqueda de la versión más corta, esto es lo que obtuve hasta ahora.

Tenga en cuenta que no existe una función perfecta que siempre detecte todas las combinaciones posibles. Es mejor conocer todas las habilidades y limitaciones de sus herramientas que esperar una herramienta mágica.


1
ligera derivación mía, A.map !== undefinedpero sí, eso podría ser un camino resbaladizo en el mundo de los patchers de mono;)
dmi3y

FYI: Esto no funciona en iFrames ( stackoverflow.com/questions/460256/… )
WiredPrairie

4
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))


4

Puedes probar esto:

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

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

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

4

Esta función convertirá casi cualquier cosa en una matriz:

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]"
}

Utiliza algunas características más nuevas del navegador, por lo que es posible que desee rellenar esto para obtener el máximo soporte.

Ejemplos:

> 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' ]

Las cadenas NB se convertirán en una matriz con un solo elemento en lugar de una matriz de caracteres. Elimine el isStringcheque si lo prefiere al revés.

Lo he usado Array.isArrayaquí porque es el más robusto y también el más simple.


4

En su caso, puede usar el concatmétodo de matriz que puede aceptar objetos individuales, así como matriz (e incluso combinados):

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 parece ser uno de los métodos más antiguos de Array (incluso IE 5.5 lo sabe bien).

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.