Come verificare se un oggetto è un array?


2753

Sto cercando di scrivere una funzione che accetta un elenco di stringhe o una singola stringa. Se è una stringa, voglio convertirla in un array con un solo elemento, in modo da poterlo scorrere senza paura di un errore.

Quindi, come posso verificare se la variabile è un array?


Ho arrotondato le varie soluzioni di seguito e creato un test jsperf . Sono tutti veloci, quindi basta usare Array.isArray: ora è ben supportato e funziona su più frame .


6
Pensavo intendessi "verificare se l'oggetto è un array", ma vuoi verificare se "l'oggetto è un array di stringhe o una singola stringa" in particolare. Non sei sicuro di vederlo? o sono solo io? Stavo pensando a qualcosa di più simile a questo ... mi manca qualcosa qui?
rr1g0,

149
TL; DR : arr.constructor === Arrayè il più veloce.
Neta,

3
jsben.ch/#/QgYAV - un punto di riferimento per i modi più comuni
EscapeNetscape

39
TL; DR - Matrice. isArray (arr) da ES5; e $. isArray (arr) in jQuery.
Ondra Žižka,

6
Ricorda solo che se per qualsiasi motivo sovrascrivi il tuo costruttore tramite prototipo, quel arr.constructor === Arraytest restituirà false. Array.isArray(arr)restituisce comunque vero comunque.
Ghaschel,

Risposte:


979

Nei browser moderni puoi farlo

Array.isArray(obj)

( Supportato da Chrome 5, Firefox 4.0, IE 9, Opera 10.5 e Safari 5)

Per compatibilità con le versioni precedenti è possibile aggiungere quanto segue

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

Se usi jQuery puoi usare jQuery.isArray(obj)o $.isArray(obj). Se usi il trattino basso puoi usare_.isArray(obj)

Se non è necessario rilevare array creati in frame diversi, è possibile utilizzare anche instanceof

obj instanceof Array

9
Ecco un elenco più completo di browser che supportanoArray.isArray
lightswitch05

if (typeof Array.isArray === 'undefined') {potrebbe essere modificato inif(!Array.isArray) {
iMatoria

Per quello che vale Object.prototype.string.call(obj)può essere falsificato se l'oggetto lo contiene Symbol.toStringTag. Detto questo, non sono a conoscenza di alcun ambiente che viene spedito, Symbol.toStringTagma non Array.isArraycosì, questo sembra sicuro.
Benjamin Gruenbaum,

5
Perché non instanceof Arrayriesce se l'array proviene da un frame diverso?
NobleUplift,

16
@NobleUplift: instanceof Arrayfallisce se l'array proviene da un frame diverso perché ogni array di quel frame diverso ha un Arraycostruttore e un prototipo diversi. Per motivi di compatibilità / sicurezza, ogni frame ha il suo ambiente globale e questo include oggetti globali. Il Objectglobale da un frame è diverso dal Objectglobale da un altro. Lo stesso Arrayvale per i globali. Axel Rauschmayer ne parla di più .
jschoi,

1943

Il metodo fornito nello standard ECMAScript per trovare la classe di Object consiste nell'utilizzare il toStringmetodo da Object.prototype.

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

Oppure potresti usare typeofper testare se è una stringa:

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

Oppure, se non sei preoccupato per le prestazioni, puoi semplicemente eseguire concatuna nuova matrice vuota.

someVar = [].concat( someVar );

C'è anche il costruttore che puoi interrogare direttamente:

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

Dai un'occhiata a un trattamento completo dal blog di @TJ Crowder , come pubblicato nel suo commento qui sotto.

Dai un'occhiata a questo benchmark per avere un'idea del metodo che funziona meglio: http://jsben.ch/#/QgYAV

Da @Bharath converti la stringa in array usando Es6 per la domanda posta:

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

supponiamo:

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ì, toStringè uno dei modi per andare. Faccio un po 'di riepilogo qui: blog.niftysnippets.org/2010/09/say-what.html
TJ Crowder

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

16
Se non si desidera digitare "[array di oggetti]", utilizzare Object.prototype.toString.call (someVar) === Object.prototype.toString.call ([]) o creare una funzione di praticità per ottenere il tipo se non si desidera voglio digitare Object.prototype.toString.call
Pramod

13
Uso la vaniglia Array.isArray che funziona nei "browser moderni" (ovvero IE9 + e tutti gli altri). E per il supporto del vecchio browser utilizzare lo spessore di MDN developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
David Gilbertson,

21
Vivere nel mondo moderno -Array.isArray(obj)
mcfedr,

1274

Vorrei prima verificare se la tua implementazione supporta isArray:

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

Puoi anche provare a usare l' instanceofoperatore

v instanceof Array

127
v instanceof Arrayrestituirà false se è vstato creato in un altro frame ( vè un'istanza di thatFrame.contentWindow.Arrayclasse).
pepkin88,

47
Per essere specifici: Array.isArrayè definito come parte di ECMAScript 5 / Javascript 1.8.5.
jevon,

8
Soluzione davvero semplice e accurata MA isArray non è compatibile con alcuni browser meno recenti (ex IE7 e IE8). Fonte: kangax.github.io/es5-compat-table/#
Wookie88

2
Che ne dici di: if (Array.isArray) restituisce Array.isArray (v); else return v instanceof Array;
lewdev,

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

298

jQuery offre anche un $.isArray()metodo:

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 utilizza internamente il metodo toString: GitHub Source
Jacob Squires,

5
@JacobSquires dipende. Ho appena testato qui, l'ultimo jQuery su Chrome - $.isArray === Array.isArraysta tornando vero.
Renan,

3
@Renan: questa è la cosa buona dell'uso di jQuery. Di solito utilizza il metodo più moderno e migliore per farlo, e non devi fare tutte le funzionalità controllando te stesso per sapere cosa usare.
timore

jQuery sta usando Array.isArraydietro le quinte: github.com/jquery/jquery/blob/master/src/core.js#L211
Sergiu

1
Ma nessuno utilizzerà JQuery SOLO PER questa funzionalità, giusto? Non vorrei semplicemente scaricare jquery perché voglio verificare se qualcosa è un array: p
Automagisch,

106

Questo è il più veloce tra tutti i metodi (tutti i browser supportati):

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

2
Hai ragione, questo è il più veloce in base ai test che ho incluso nella domanda.
Aprire il

5
Ci sono degli svantaggi nell'utilizzo di questo metodo? Sembra molto più semplice ed efficace della risposta accettata e migliore.
David Meza,

@shinobi - solo curioso (e l'ho visto spesso) - perché dici la condizione if (obj && Array === obj.constructor)al contrario if (obj && obj.constructor === Array)? È perso nella traduzione in inglese, quindi per codificare cosa? ad esempio, chi parla inglese generalmente tende a chiedere "esiste l'oggetto e il suo costruttore proviene dalla classe array?", quindi il flusso di codice durante la lettura è più logico. o c'è qualche motivo tecnico?
non sincronizzato il

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();}
non sincronizzato il

3
@shinobi tutto bene. suppongo che potrebbe essere una sbronza per abitudine sicura - se usi accidentalmente = invece di ==, non si comporterebbe perché non è una variabile assegnabile.
non sincronizzato il

47

Immagina di avere questo array di seguito :

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

Javascript (browser nuovi e meno recenti):

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

quindi chiamalo così:

isArray(arr);

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

Array.isArray(arr);

jQuery:

$.isArray(arr);

Angolare:

angular.isArray(arr);

Underscore e Lodash:

_.isArray(arr);

34

Array.isArray funziona velocemente, ma non è supportato da tutte le versioni di browser. Quindi potresti fare un'eccezione per gli altri e usare il metodo universale:

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

3
È necessario ottenere il .toString()metodo da Object.prototype. In questo momento stai usando il window.toString(), che non è lo stesso.
il sistema

Hai ragione. window.toStringfare lo stesso come Object.prototype.toStringsolo in Chrome.
CruorVult,

isArray non è affatto veloce. È il metodo più lento.
jemiloii,

Perché non aggiungerlo semplicemente all'array piuttosto che agli utensili? (So ​​che non vuoi proprietà extra su nuovi oggetti array ma penso che ciò accada solo se aggiungi isArray ad Array.prototype.)
David Winiecki,

27

Semplice funzione per controllare questo:

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

16
Lo ridurrei fino a una riga return object.constructor === Array, ma sei sicuro che questo tornerà vero solo per gli array?
mpen

12
Puoi farlo con tutte le espressioni booleane. Mi fa impazzire quando vedo if(x) return true; else return false:-) Anche se è all'indietro, dovresti negare l'espressione.
mpen

3
Il motivo per cui ciò non restituisce true per getElementsByTagName è perché il risultato di quella funzione è in realtà un HTMLCollection e non un array.
Yuval A.

6
Ciò ha esito negativo se l'oggetto non è definito o è nullo.
John Henckel,

1
@JohnHenckel Vedere la mia risposta stackoverflow.com/a/29400289/34806 prende in considerazione sia la vostra preoccupazione, così come il primo commento, il tutto su una riga
Dexygen

17

Come dice MDN qui :

usa Array.isArray o Object.prototype.toString.call per differenziare gli oggetti regolari dagli array

Come questo:

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

  • Array.isArray(arr)


17

C'è solo una soluzione per questa domanda

x instanceof Array

dove x è la variabile restituirà vero se x è un array e falso in caso contrario.


Molto più pulito e sicuro per il futuro! Questo o un typeofconfronto.
ChristoKiwi,

È qualcosa che riceve una buona quantità di supporto per il browser? Mi piace.
Dan Zuzevich,

1
Sfortunatamente, questo non è effettivamente utile senza un tentativo / cattura perché se "x" è un oggetto come {}un array, si ottiene un errore di sintassi.
abalter

15

È possibile verificare il tipo di variabile se si tratta di un array con;

var myArray=[];

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

1
Alcune persone hanno già menzionato instanceof.. Penso che fallisca in alcuni scenari strani.
Aprire il

15

Vorrei fare una funzione per testare il tipo di oggetto con cui hai a che fare ...

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

allora puoi scrivere una semplice istruzione if ...

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

12

Lo faccio in un modo molto semplice. Per me va bene. Qualche inconveniente?

Array.prototype.isArray = true;

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

7
imbrogliato da{isArray:true}
Bergi il

JSON.parse(someDataFromElsewhere).items.isArraypotrebbe restituire true (in base ai dati) e violare il codice.
Roy Tinker,

12

Questo è il mio tentativo di migliorare questa risposta tenendo conto dei commenti:

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

Elimina if / else e tiene conto della possibilità che l'array sia nullo o indefinito


costruttore non è disponibile in ES5
TechTurtle il


11

Ho aggiornato il violino jsperf con due metodi alternativi e il controllo degli errori.

Si scopre che il metodo che definisce un valore costante nei prototipi "Oggetto" e "Array" è più veloce di qualsiasi altro metodo. È un risultato alquanto 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/>");

Questi due metodi non funzionano se la variabile accetta il valore indefinito, ma funzionano se si è certi di avere un valore. Per quanto riguarda il controllo tenendo presente le prestazioni se un valore è un array o un singolo valore, il secondo metodo sembra un metodo veloce valido. È leggermente più veloce di "instanceof" su Chrome, due volte più veloce del secondo metodo migliore in Internet Explorer, Opera e Safari (sulla mia macchina).


9

So che le persone sono alla ricerca di una sorta di approccio javascript non elaborato. Ma se vuoi pensarci meno, dai un'occhiata qui: http://underscorejs.org/#isArray

_.isArray(object) 

Restituisce vero se l'oggetto è un array.

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

7
"A meno che non sia incluso un altro tag per un framework / libreria, è prevista una risposta JavaScript pura."
Michał Perłakowski,

5

La migliore soluzione che ho visto è una sostituzione cross-browser per typeof. Controlla qui la soluzione di Angus Croll .

La versione TL; DR è sotto, ma l'articolo è una grande discussione del problema, quindi dovresti leggerlo se hai tempo.

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

Ecco il mio approccio pigro:

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

// ...

var test = [],
    wat = {};

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

So che è sacrilegio "scherzare" con il prototipo, ma sembra funzionare in modo significativamente migliore rispetto al toStringmetodo raccomandato .

Nota: una trappola di questo approccio è che non funzionerà oltre i iframeconfini , ma per il mio caso d'uso questo non è un problema.


non è più migliore in termini di prestazioni, almeno su FF30 su Ubuntu 64-bit
test30

2
ingannato dagli wat = {array_: true}oggetti.
Bergi,

@Bergi: Sì, dovrebbe essere ovvio. Se stai impostando obj.array_ = true, allora stai solo prendendo in giro te stesso .
namuol,

@namuol: non mi sto necessariamente prendendo in giro. Spesso abbastanza oggetti sono usati come dizionari. Pensa a un cacheoggetto per memorizzare i risultati della ricerca che utilizza le stringhe di ricerca come chiavi di proprietà. Cosa succede se un utente cerca array_? Il tuo oggetto diventa un array per questo? È solo un bug.
Bergi,

@namuol: Inoltre, questo approccio richiederebbe che tutte le parti coinvolte (comprese le librerie usate) possano concordare che .array_è usato per etichettare gli array. Questo non è davvero il caso qui, .arraypuò significare qualsiasi cosa. Dovresti almeno usare una stringa descrittiva e segnalare inadeguatezza dell'uso arbitrario, ad es .__isArray = true. Con .
Bergi,

5

C'è un bell'esempio nel libro JavaScript Patterns di Stoyan Stefanov che suppone di gestire tutti i possibili problemi e di utilizzare il metodo ECMAScript 5 Array.isArray () .

Quindi eccolo qui:

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

A proposito, se stai usando jQuery, puoi usare il suo metodo $ .isArray ()


2
+1: perché non solo un semplice if(!Array.isArray) {...?
Marco Demaio,

5

modo più semplice e veloce per verificare se un oggetto è un array o meno.

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

o

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

oppure puoi fare una funzione di utilità:

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

utilizzo:

isArray(arr); //return true

5

Quanto segue potrebbe essere usato se sai che il tuo oggetto non ha un metodo concat.

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


Questo è un buon trucco, ma potrebbe essere ignorato ... ma la maggior parte delle volte dovrebbe ottenere il risultato
Alireza

5

Potresti è il metodo isArray ma preferirei verificare

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


Perché preferisci questo?
aprono il

@mpen Object.getPrototypeOf(yourvariable)restituisce il prototipo di un oggetto Array. E il codice è più veloce e sicuro su cui contare.
ACCIAIO

1
È facile da sventare: pastebin.com/MP8d5bCE Inoltre, hai dei test delle prestazioni per eseguire il backup del tuo reclamo "più veloce"?
mpen

4

Se gli unici due tipi di valori che possono essere passati a questa funzione sono una stringa o una matrice di stringhe, mantienila semplice e usa un typeofcontrollo per la possibilità della stringa:

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

Sì ... funzionerebbe per questo scenario, ma non in generale. Finì comunque usando varargs. :)
mpen

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

Alla ricerca della versione più breve ecco quello che ho ottenuto finora.

Nota, non esiste una funzione perfetta che rileverà sempre tutte le possibili combinazioni. È meglio conoscere tutte le abilità e le limitazioni dei tuoi strumenti piuttosto che aspettarti uno strumento magico.


1
leggera derivazione mia A.map !== undefinedma sì, quella potrebbe essere una strada scivolosa nel mondo dei patcher di scimmie;)
dmi3y

FYI: Questo non funziona attraverso iFrame ( 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

Una semplice funzione per verificare se un valore di input è un array è la seguente:

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

Funziona su più browser e con browser meno recenti. Questo è tratto dal post sul blog di TJ Crowders


4

Puoi provare questo:

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

Questa funzione trasformerà quasi tutto in un array:

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

Utilizza alcune funzionalità del browser più recenti, quindi potresti volerlo riempire per il massimo supporto.

Esempi:

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

Le stringhe NB verranno convertite in un array con un singolo elemento anziché un array di caratteri. Elimina il isStringsegno di spunta se lo preferisci viceversa.

Ho usato Array.isArrayqui perché è il più robusto e anche il più semplice.


4

Nel tuo caso puoi usare il concatmetodo di array che può accettare singoli oggetti e array (e persino combinato):

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 sembra essere uno dei metodi più antichi di array (anche IE 5.5 lo sa bene).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.